{"id":528,"date":"2011-04-13T02:25:41","date_gmt":"2011-04-13T02:25:41","guid":{"rendered":"\/blogs\/jonathan\/post\/Does-Index-Fragmentation-Matter-with-SSDe28099s.aspx"},"modified":"2017-04-13T14:41:45","modified_gmt":"2017-04-13T18:41:45","slug":"does-index-fragmentation-matter-with-ssds","status":"publish","type":"post","link":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/","title":{"rendered":"Does Index Fragmentation Matter with SSD\u2019s?"},"content":{"rendered":"<p>Two weeks ago at SQL Connections in Orlando, FL, I got to participate in a session that Paul and Kimberly do at the end of the conference titled, \u201cFollow the Rabbit.\u201d&#160; The premise of the session is that Paul and Kimberly throw a big list of topics up on the screen and anyone in the audience can ask any question they have about one of those topics and Paul and Kimberly will try to answer it.&#160; I wasn\u2019t the only person to end up participating in this session answering questions, Maciej Pilecki another MVP who also recently passed the Microsoft Certified Masters Exam for SQL Server 2008 answered a number of questions as well.&#160; One of my favorite questions that was asked during this session was \u201cDoes index fragmentation matter with SSD\u2019s anymore?\u201d&#160; Paul\u2019s answer to the question was very practical and dealt with the wasted space utilization that excessive index fragmentation can cause in a database that uses a uniqueidentifier column with newid() as the primary key, and given the cost per gigabyte for SSD storage this could be quite significant.&#160; Paul pointed out a couple of other points that escape me, primarily because my mind immediately started churning ideas about how to test the impact that index fragmentation actually has on a database.<\/p>\n<p>It should be no surprise that this blog post is going to use Extended Events, it has after all been my favorite feature in SQL Server since it was first released in an early CTP for SQL Server 2008.&#160; One of the sessions that I presented at SQL Connections last month was on Extended Events and I made some pretty heavy use of the I\/O related events as a part of that session.&#160; I also made heavy usage of the I\/O related events back in December for a couple of my <a href=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/category\/xevent-a-day-series\/\" target=\"_blank\">XEvent a Day blog posts<\/a>, so I knew that I could really get some detailed information back from the system about what kind of impact fragmentation really had on a database, and since I have a SSD in my laptop, which while not enterprise class is more than worthy of performing the tests on, I thought I\u2019d give a whirl at figuring out how much impact fragmentation really had.<\/p>\n<p>When I began working on this problem, I started out using Windows Server 2008R2 and SQL Server 2008R2, primarily because it is my standard VM platform for the <a href=\"https:\/\/www.sqlskills.com\/sql-server-training\/immersion-events-schedule\/\" target=\"_blank\">Immersion Training<\/a>, and for presentations and it was immediately available. I originally intended to use the I\/O size information from the file_read_completed event to aggregate the I\/O sizes being read from disk, and I soon learned that this was not available in SQL Server 2008 as I had originally thought.&#160; I knew I had used it in the past so I went back to my XEvent a Day blog series and found <a href=\"https:\/\/www.sqlskills.com\/blogs\/jonathan\/an-xevent-a-day-29-of-31-the-future-looking-at-database-startup-in-denali\/\" target=\"_blank\">An XEvent a Day (29 of 31) \u2013 The Future \u2013 Looking at Database Startup in Denali<\/a>.&#160; <\/p>\n<p>Bummer!<\/p>\n<p>I happened to have my old Denali CTP1 VM that I used to create that blog post on a external hard disk so I decided to make use of it for the investigation.&#160; I had originally hoped to be able to create a reproducible demo that anyone could use in their SQL Server 2008 environment to see the impact of fragmentation, but since it is not possible this post will be based on the information available through SQL Server Denali instead.<\/p>\n<p>The first thing that we will need is a database with two tables that have identical data in them; one fragmented and the other not. To create this, we\u2019ll use a uniqueidentifier with newid() as the primary key for the first table and a uniqueidentifier with newsequentialid() as the primary key for the second table. Then we will load approximately 1000 pages worth of data into the first table and then copy that data into the second table, and rebuild the indexes on the second table to remove any residual fragmentation from it.<\/p>\n<blockquote>\n<div class=\"csharpcode\">\n<pre class=\"alt\"><span class=\"kwrd\">CREATE<\/span> <span class=\"kwrd\">DATABASE<\/span> FragmentationTest<\/pre>\n<pre><span class=\"kwrd\">GO<\/span><\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">USE<\/span> FragmentationTest<\/pre>\n<pre><span class=\"kwrd\">GO<\/span><\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">CREATE<\/span> <span class=\"kwrd\">TABLE<\/span> GuidHighFragmentation<\/pre>\n<pre>(UniqueID UNIQUEIDENTIFIER <span class=\"kwrd\">DEFAULT<\/span> NEWID() <span class=\"kwrd\">PRIMARY<\/span> <span class=\"kwrd\">KEY<\/span>,<\/pre>\n<pre class=\"alt\"> FirstName nvarchar(50) <span class=\"kwrd\">NOT<\/span> <span class=\"kwrd\">NULL<\/span>,<\/pre>\n<pre> LastName nvarchar(50) <span class=\"kwrd\">NOT<\/span> <span class=\"kwrd\">NULL<\/span>)<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">CREATE<\/span> <span class=\"kwrd\">NONCLUSTERED<\/span> <span class=\"kwrd\">INDEX<\/span> IX_GuidHighFragmentation_LastName<\/pre>\n<pre><span class=\"kwrd\">ON<\/span> GuidHighFragmentation(LastName)<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">CREATE<\/span> <span class=\"kwrd\">TABLE<\/span> GuidLowFragmentation<\/pre>\n<pre>(UniqueID UNIQUEIDENTIFIER <span class=\"kwrd\">DEFAULT<\/span> NEWSEQUENTIALID() <span class=\"kwrd\">PRIMARY<\/span> <span class=\"kwrd\">KEY<\/span>,<\/pre>\n<pre class=\"alt\"> FirstName nvarchar(50) <span class=\"kwrd\">NOT<\/span> <span class=\"kwrd\">NULL<\/span>,<\/pre>\n<pre> LastName nvarchar(50) <span class=\"kwrd\">NOT<\/span> <span class=\"kwrd\">NULL<\/span>)<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">CREATE<\/span> <span class=\"kwrd\">NONCLUSTERED<\/span> <span class=\"kwrd\">INDEX<\/span> IX_GuidLowFragmentation_LastName<\/pre>\n<pre><span class=\"kwrd\">ON<\/span> GuidLowFragmentation(LastName)<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\">INSERT <span class=\"kwrd\">INTO<\/span> GuidHighFragmentation (FirstName, LastName)<\/pre>\n<pre><span class=\"kwrd\">SELECT<\/span> <span class=\"kwrd\">TOP<\/span> 1000<\/pre>\n<pre class=\"alt\">    a.name, b.name<\/pre>\n<pre><span class=\"kwrd\">FROM<\/span> master.dbo.spt_values <span class=\"kwrd\">AS<\/span> a<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">CROSS<\/span> <span class=\"kwrd\">JOIN<\/span> master.dbo.spt_values <span class=\"kwrd\">AS<\/span> b<\/pre>\n<pre><span class=\"kwrd\">WHERE<\/span> a.name <span class=\"kwrd\">IS<\/span> <span class=\"kwrd\">NOT<\/span> <span class=\"kwrd\">NULL<\/span> <\/pre>\n<pre class=\"alt\">    <span class=\"kwrd\">AND<\/span> b.name <span class=\"kwrd\">IS<\/span> <span class=\"kwrd\">NOT<\/span> <span class=\"kwrd\">NULL<\/span><\/pre>\n<pre><span class=\"kwrd\">ORDER<\/span> <span class=\"kwrd\">BY<\/span> NEWID()<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span> 70<\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\">INSERT <span class=\"kwrd\">INTO<\/span> GuidLowFragmentation (FirstName, LastName)<\/pre>\n<pre><span class=\"kwrd\">SELECT<\/span> FirstName, LastName<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">FROM<\/span> GuidHighFragmentation<\/pre>\n<pre><span class=\"kwrd\">GO<\/span><\/pre>\n<pre class=\"alt\">&#160;<\/pre>\n<pre><span class=\"kwrd\">ALTER<\/span> <span class=\"kwrd\">INDEX<\/span> <span class=\"kwrd\">ALL<\/span> <span class=\"kwrd\">ON<\/span> GuidLowFragmentation REBUILD<\/pre>\n<\/p><\/div>\n<\/blockquote>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n<p>With our tables built, we can validate the fragmentation information by querying the sys.dm_index_physical_stats() DMF:<\/p>\n<blockquote>\n<div class=\"csharpcode\">\n<pre class=\"alt\"><span class=\"kwrd\">SELECT<\/span> <\/pre>\n<pre>    OBJECT_NAME(ps.object_id),<\/pre>\n<pre class=\"alt\">    i.name,<\/pre>\n<pre>    ps.index_id,<\/pre>\n<pre class=\"alt\">    ps.index_depth,<\/pre>\n<pre>    avg_fragmentation_in_percent,<\/pre>\n<pre class=\"alt\">    fragment_count,<\/pre>\n<pre>    page_count,<\/pre>\n<pre class=\"alt\">    avg_page_space_used_in_percent,<\/pre>\n<pre>    record_count<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">FROM<\/span> sys.dm_db_index_physical_stats(<\/pre>\n<pre>        DB_ID(), <\/pre>\n<pre class=\"alt\">        <span class=\"kwrd\">NULL<\/span>, <\/pre>\n<pre>        <span class=\"kwrd\">NULL<\/span>, <\/pre>\n<pre class=\"alt\">        <span class=\"kwrd\">NULL<\/span>, <\/pre>\n<pre>        <span class=\"str\">'DETAILED'<\/span>) <span class=\"kwrd\">AS<\/span> ps<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">JOIN<\/span> sys.indexes <span class=\"kwrd\">AS<\/span> i<\/pre>\n<pre>    <span class=\"kwrd\">ON<\/span> ps.object_id = i.object_id<\/pre>\n<pre class=\"alt\">        <span class=\"kwrd\">AND<\/span> ps.index_id = i.index_id<\/pre>\n<pre><span class=\"kwrd\">WHERE<\/span> index_level = 0<\/pre>\n<\/p><\/div>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n<\/blockquote>\n<p><a href=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/7d018f4f\/image.png\" target=\"_blank\"><img decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/632d5920\/image_thumb.png\" width=\"644\" height=\"60\" \/><\/a><\/p>\n<p>Next we will create our event session to capture the I\/O events that are related to physical reads from disk.&#160; The event session is being created using dynamic SQL so that each of the events has a predicate on the sqlserver.database_id for the current database.<\/p>\n<blockquote>\n<div class=\"csharpcode\">\n<pre class=\"alt\"><span class=\"rem\">-- Create an Event Session to investigate our IO operations<\/span><\/pre>\n<pre><span class=\"kwrd\">IF<\/span> <span class=\"kwrd\">EXISTS<\/span>(<span class=\"kwrd\">SELECT<\/span> * <span class=\"kwrd\">FROM<\/span> sys.server_event_sessions <span class=\"kwrd\">WHERE<\/span> name=<span class=\"str\">'FragmentationEffect'<\/span>)<\/pre>\n<pre class=\"alt\">    <span class=\"kwrd\">DROP<\/span> EVENT <span class=\"kwrd\">SESSION<\/span> [FragmentationEffect] <span class=\"kwrd\">ON<\/span> SERVER;<\/pre>\n<pre><span class=\"kwrd\">DECLARE<\/span> @sqlcmd nvarchar(4000) = <span class=\"str\">'<\/pre>\n<pre class=\"alt\">CREATE EVENT SESSION FragmentationEffect<\/pre>\n<pre>ON SERVER<\/pre>\n<pre class=\"alt\">ADD EVENT sqlserver.sql_statement_starting<\/pre>\n<pre>( ACTION (sqlserver.sql_text)),<\/pre>\n<pre class=\"alt\">ADD EVENT sqlserver.sql_statement_completed<\/pre>\n<pre>( ACTION (sqlserver.sql_text)),<\/pre>\n<pre class=\"alt\">ADD EVENT sqlserver.file_read<\/pre>\n<pre>( WHERE (sqlserver.database_id = '<\/span>+ <span class=\"kwrd\">cast<\/span>(DB_ID() <span class=\"kwrd\">as<\/span> <span class=\"kwrd\">varchar<\/span>(3))+<span class=\"str\">')),<\/pre>\n<pre class=\"alt\">ADD EVENT sqlserver.file_read_completed<\/pre>\n<pre>( WHERE (sqlserver.database_id = '<\/span>+ <span class=\"kwrd\">cast<\/span>(DB_ID() <span class=\"kwrd\">as<\/span> <span class=\"kwrd\">varchar<\/span>(3))+<span class=\"str\">')),<\/pre>\n<pre class=\"alt\">ADD EVENT sqlserver.physical_page_read<\/pre>\n<pre>( WHERE (sqlserver.database_id = '<\/span>+ <span class=\"kwrd\">cast<\/span>(DB_ID() <span class=\"kwrd\">as<\/span> <span class=\"kwrd\">varchar<\/span>(3))+<span class=\"str\">')),<\/pre>\n<pre class=\"alt\">ADD EVENT sqlos.async_io_requested<\/pre>\n<pre>( WHERE (sqlserver.database_id = '<\/span>+ <span class=\"kwrd\">cast<\/span>(DB_ID() <span class=\"kwrd\">as<\/span> <span class=\"kwrd\">varchar<\/span>(3))+<span class=\"str\">')),<\/pre>\n<pre class=\"alt\">ADD EVENT sqlos.async_io_completed<\/pre>\n<pre>( WHERE (sqlserver.database_id = '<\/span>+ <span class=\"kwrd\">cast<\/span>(DB_ID() <span class=\"kwrd\">as<\/span> <span class=\"kwrd\">varchar<\/span>(3))+<span class=\"str\">'))--,<\/pre>\n<pre class=\"alt\">ADD TARGET package0.asynchronous_file_target(<\/pre>\n<pre>     SET filename='<\/span><span class=\"str\">'C:\\SQLskills\\EE_FragmentationEffect.xel'<\/span><span class=\"str\">',<\/pre>\n<pre class=\"alt\">         metadatafile='<\/span><span class=\"str\">'C:\\SQLskills\\EE_FragmentationEffect.xem'<\/span><span class=\"str\">')<\/pre>\n<pre>WITH (MAX_MEMORY = 8MB, EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS, <\/pre>\n<pre class=\"alt\">      TRACK_CAUSALITY = ON, MAX_DISPATCH_LATENCY=5SECONDS)'<\/span><\/pre>\n<pre><span class=\"kwrd\">EXEC<\/span> (@sqlcmd)<\/pre>\n<pre class=\"alt\">GO<\/pre>\n<\/p><\/div>\n<\/blockquote>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n<p>This event session is configured to have MAX_MEMORY set at 8MB to account for the partitioning of the memory buffers and to ensure that there is ample buffer space for the session to try and mitigate against the potential for event loss.&#160; The EVENT_RETENTION_MODE for the session can not be configured for NO_EVENT_LOSS since the sqlserver.physical_page_read event is a part of the event session.&#160; TRACK_CAUSALITY is turned ON for the event session so that correlation between events can be made to tie the I\/O operations back to the statement that generated them, and the MAX_DISPATCH_LATENCY has been set at five seconds because I am impatient and don\u2019t want to have to wait the default of thirty seconds for the events to be dispatched to the targets while doing a demo.<\/p>\n<p>Prior to starting the event session, a manual CHECKPOINT will be issued against the database to flush any dirty pages from the buffer cache to disk, and then the buffer cache will be cleared using DBCC DROPCLEANBUFFERS to ensure that the test statements have to physically read the data from disk into cache.<\/p>\n<blockquote>\n<div class=\"csharpcode\">\n<pre class=\"alt\"><span class=\"rem\">-- Issue checkpoint to flush dirty buffers to disk<\/span><\/pre>\n<pre><span class=\"kwrd\">CHECKPOINT<\/span><\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\"><span class=\"rem\">-- Clear the Buffer Cache to force reads from Disk <\/span><\/pre>\n<pre><span class=\"kwrd\">DBCC<\/span> DROPCLEANBUFFERS <\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span> <\/pre>\n<\/p><\/div>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n<\/blockquote>\n<p>With this completed, we can now start our event session and run the same query against each table to force a scan of all the pages in the table from disk, then stop the event session so that our target file only has events associated with this specific test in it.<\/p>\n<blockquote>\n<div class=\"csharpcode\">\n<pre class=\"alt\"><span class=\"rem\">-- Start the Event Session<\/span><\/pre>\n<pre><span class=\"kwrd\">ALTER<\/span> EVENT <span class=\"kwrd\">SESSION<\/span> FragmentationEffect<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">ON<\/span> SERVER<\/pre>\n<pre><span class=\"kwrd\">STATE<\/span>=<span class=\"kwrd\">START<\/span><\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\"><span class=\"rem\">-- Aggregate the data from both tables <\/span><\/pre>\n<pre><span class=\"kwrd\">SELECT<\/span> LastName, <span class=\"kwrd\">COUNT<\/span>(*)<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">FROM<\/span> GuidLowFragmentation<\/pre>\n<pre><span class=\"kwrd\">GROUP<\/span> <span class=\"kwrd\">BY<\/span> LastName<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span>        <\/pre>\n<pre><span class=\"kwrd\">SELECT<\/span> LastName, <span class=\"kwrd\">COUNT<\/span>(*)<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">FROM<\/span> GuidHighFragmentation<\/pre>\n<pre><span class=\"kwrd\">GROUP<\/span> <span class=\"kwrd\">BY<\/span> LastName<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\"><span class=\"rem\">-- Wait for the events to dispatch to the target<\/span><\/pre>\n<pre><span class=\"kwrd\">WAITFOR<\/span> DELAY <span class=\"str\">'00:00:10'<\/span><\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\"><span class=\"rem\">-- Stop the Event Session<\/span><\/pre>\n<pre><span class=\"kwrd\">ALTER<\/span> EVENT <span class=\"kwrd\">SESSION<\/span> FragmentationEffect<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">ON<\/span> SERVER<\/pre>\n<pre><span class=\"kwrd\">STATE<\/span>=STOP<\/pre>\n<pre class=\"alt\">GO<\/pre>\n<\/p><\/div>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n<\/blockquote>\n<p>Now that we have our data, we need to read it from the file and break down the event data into columns to simplify analysis of the information.&#160; To do this, we\u2019ll first load the event data as XML into a staging table.&#160; Trying to parse the XML while reading from the file through the DMF is incredibly slow by comparison.&#160; Then we can shred the XML into a tabular format based on the events being collected.<\/p>\n<blockquote>\n<div class=\"csharpcode\">\n<pre class=\"alt\"><span class=\"rem\">-- Drop Results tables if they exist<\/span><\/pre>\n<pre><span class=\"kwrd\">IF<\/span> OBJECT_ID(<span class=\"str\">'FragmentationEffectResults'<\/span>) <span class=\"kwrd\">IS<\/span> <span class=\"kwrd\">NOT<\/span> <span class=\"kwrd\">NULL<\/span><\/pre>\n<pre class=\"alt\">    <span class=\"kwrd\">DROP<\/span> <span class=\"kwrd\">TABLE<\/span> FragmentationEffectResults <\/pre>\n<pre><span class=\"kwrd\">GO<\/span><\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">IF<\/span> OBJECT_ID(<span class=\"str\">'FragmentationEffectResultsParsed'<\/span>) <span class=\"kwrd\">IS<\/span> <span class=\"kwrd\">NOT<\/span> <span class=\"kwrd\">NULL<\/span><\/pre>\n<pre>    <span class=\"kwrd\">DROP<\/span> <span class=\"kwrd\">TABLE<\/span> FragmentationEffectResultsParsed <\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\"><span class=\"rem\">-- Create results table to load data from XE files<\/span><\/pre>\n<pre><span class=\"kwrd\">CREATE<\/span> <span class=\"kwrd\">TABLE<\/span> FragmentationEffectResults<\/pre>\n<pre class=\"alt\">(RowID <span class=\"kwrd\">int<\/span> <span class=\"kwrd\">identity<\/span> <span class=\"kwrd\">primary<\/span> <span class=\"kwrd\">key<\/span>, event_data XML)<\/pre>\n<pre><span class=\"kwrd\">GO<\/span><\/pre>\n<pre class=\"alt\">&#160;<\/pre>\n<pre><span class=\"rem\">-- Load the event data from the file target<\/span><\/pre>\n<pre class=\"alt\">INSERT <span class=\"kwrd\">INTO<\/span> FragmentationEffectResults(event_data)<\/pre>\n<pre><span class=\"kwrd\">SELECT<\/span><\/pre>\n<pre class=\"alt\">    <span class=\"kwrd\">CAST<\/span>(event_data <span class=\"kwrd\">AS<\/span> XML) <span class=\"kwrd\">AS<\/span> event_data<\/pre>\n<pre><span class=\"kwrd\">FROM<\/span> sys.fn_xe_file_target_read_file(<span class=\"str\">'C:\\SQLskills\\EE_FragmentationEffect*.xel'<\/span>, <\/pre>\n<pre class=\"alt\">                                     <span class=\"str\">'C:\\SQLskills\\EE_FragmentationEffect*.xem'<\/span>, <\/pre>\n<pre>                                     <span class=\"kwrd\">null<\/span>, <span class=\"kwrd\">null<\/span>)<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">GO<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\"><span class=\"rem\">-- Parse the event data<\/span><\/pre>\n<pre><span class=\"kwrd\">SELECT<\/span> <\/pre>\n<pre class=\"alt\">    RowID,<\/pre>\n<pre>    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/@name)[1]'<\/span>, <span class=\"str\">'varchar(50)'<\/span>) <span class=\"kwrd\">AS<\/span> event_name,<\/pre>\n<pre class=\"alt\">    DATEADD(hh, <\/pre>\n<pre>            DATEDIFF(hh, GETUTCDATE(), <span class=\"kwrd\">CURRENT_TIMESTAMP<\/span>), <\/pre>\n<pre class=\"alt\">            event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/@timestamp)[1]'<\/span>, <span class=\"str\">'datetime2'<\/span>)) <span class=\"kwrd\">AS<\/span> [<span class=\"kwrd\">timestamp<\/span>],<\/pre>\n<pre>    <span class=\"kwrd\">COALESCE<\/span>(event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;database_id&quot;]\/value)[1]'<\/span>, <span class=\"str\">'int'<\/span>), <\/pre>\n<pre class=\"alt\">             event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/action[@name=&quot;database_id&quot;]\/value)[1]'<\/span>, <span class=\"str\">'int'<\/span>)) <span class=\"kwrd\">AS<\/span> database_id,<\/pre>\n<pre>    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;mode&quot;]\/text)[1]'<\/span>, <span class=\"str\">'nvarchar(4000)'<\/span>) <span class=\"kwrd\">AS<\/span> [mode],<\/pre>\n<pre class=\"alt\">    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;file_handle&quot;]\/value)[1]'<\/span>, <span class=\"str\">'nvarchar(4000)'<\/span>) <span class=\"kwrd\">AS<\/span> [file_handle],<\/pre>\n<pre>    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;offset&quot;]\/value)[1]'<\/span>, <span class=\"str\">'bigint'<\/span>) <span class=\"kwrd\">AS<\/span> [offset],<\/pre>\n<pre class=\"alt\">    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;page_id&quot;]\/value)[1]'<\/span>, <span class=\"str\">'int'<\/span>) <span class=\"kwrd\">AS<\/span> [page_id],<\/pre>\n<pre>    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;file_id&quot;]\/value)[1]'<\/span>, <span class=\"str\">'int'<\/span>) <span class=\"kwrd\">AS<\/span> [file_id],<\/pre>\n<pre class=\"alt\">    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;file_group_id&quot;]\/value)[1]'<\/span>, <span class=\"str\">'int'<\/span>) <span class=\"kwrd\">AS<\/span> [file_group_id],<\/pre>\n<pre>    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;size&quot;]\/value)[1]'<\/span>, <span class=\"str\">'bigint'<\/span>) <span class=\"kwrd\">AS<\/span> [<span class=\"kwrd\">size<\/span>],<\/pre>\n<pre class=\"alt\">    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;wait_type&quot;]\/text)[1]'<\/span>, <span class=\"str\">'nvarchar(100)'<\/span>) <span class=\"kwrd\">AS<\/span> [wait_type],<\/pre>\n<pre>    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;duration&quot;]\/value)[1]'<\/span>, <span class=\"str\">'bigint'<\/span>) <span class=\"kwrd\">AS<\/span> [duration],<\/pre>\n<pre class=\"alt\">    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/action[@name=&quot;sql_text&quot;]\/value)[1]'<\/span>, <span class=\"str\">'nvarchar(4000)'<\/span>) <span class=\"kwrd\">AS<\/span> [sql_text],<\/pre>\n<pre>    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;cpu&quot;]\/value)[1]'<\/span>, <span class=\"str\">'int'<\/span>) <span class=\"kwrd\">AS<\/span> [cpu],<\/pre>\n<pre class=\"alt\">    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;reads&quot;]\/value)[1]'<\/span>, <span class=\"str\">'bigint'<\/span>) <span class=\"kwrd\">AS<\/span> [<span class=\"kwrd\">reads<\/span>],<\/pre>\n<pre>    event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/data[@name=&quot;writes&quot;]\/value)[1]'<\/span>, <span class=\"str\">'bigint'<\/span>) <span class=\"kwrd\">AS<\/span> [writes],<\/pre>\n<pre class=\"alt\">    <span class=\"kwrd\">CAST<\/span>(<span class=\"kwrd\">SUBSTRING<\/span>(event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/action[@name=&quot;attach_activity_id&quot;]\/value)[1]'<\/span>, <span class=\"str\">'varchar(50)'<\/span>), 1, 36) <span class=\"kwrd\">AS<\/span> uniqueidentifier) <span class=\"kwrd\">as<\/span> activity_id,<\/pre>\n<pre>    <span class=\"kwrd\">CAST<\/span>(<span class=\"kwrd\">SUBSTRING<\/span>(event_data.<span class=\"kwrd\">value<\/span>(<span class=\"str\">'(event\/action[@name=&quot;attach_activity_id&quot;]\/value)[1]'<\/span>, <span class=\"str\">'varchar(50)'<\/span>), 38, 10) <span class=\"kwrd\">AS<\/span> <span class=\"kwrd\">int<\/span>) <span class=\"kwrd\">as<\/span> event_sequence<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">INTO<\/span> FragmentationEffectResultsParsed<\/pre>\n<pre><span class=\"kwrd\">FROM<\/span> FragmentationEffectResults<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">ORDER<\/span> <span class=\"kwrd\">BY<\/span> Rowid<\/pre>\n<\/p><\/div>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n<\/blockquote>\n<p>This is where the real fun begins.&#160; There are too many events in results set to be useful in raw form, so what I decided to do was to locate the activity_id from TRACK_CAUSALITY for the sqlserver.sql_statement_starting events for both of the tables, and store those into variables for use in querying off the results set.&#160; The first thing I looked at was how many times did each of the events actually fire for each of the tables.<\/p>\n<blockquote>\n<div class=\"csharpcode\">\n<pre class=\"alt\"><span class=\"kwrd\">DECLARE<\/span> @FragmentationHighActivityID <span class=\"kwrd\">varchar<\/span>(50),<\/pre>\n<pre>        @FragmentationLowActivityID <span class=\"kwrd\">varchar<\/span>(50)<\/pre>\n<pre class=\"alt\">        <\/pre>\n<pre><span class=\"kwrd\">SELECT<\/span> @FragmentationHighActivityID = activity_id<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">FROM<\/span> FragmentationEffectResultsParsed<\/pre>\n<pre><span class=\"kwrd\">WHERE<\/span> event_name = <span class=\"str\">'sql_statement_starting'<\/span><\/pre>\n<pre class=\"alt\">  <span class=\"kwrd\">AND<\/span> sql_text <span class=\"kwrd\">LIKE<\/span> <span class=\"str\">'%GuidHighFragmentation%'<\/span><\/pre>\n<pre>&#160;<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">SELECT<\/span> @FragmentationLowActivityID = activity_id<\/pre>\n<pre><span class=\"kwrd\">FROM<\/span> FragmentationEffectResultsParsed<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">WHERE<\/span> event_name = <span class=\"str\">'sql_statement_starting'<\/span><\/pre>\n<pre>  <span class=\"kwrd\">AND<\/span> sql_text <span class=\"kwrd\">LIKE<\/span> <span class=\"str\">'%GuidLowFragmentation%'<\/span><\/pre>\n<pre class=\"alt\">&#160;<\/pre>\n<pre><span class=\"rem\">-- Aggregate the results by the event name and file_id<\/span><\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">SELECT<\/span> event_name, <\/pre>\n<pre>    <span class=\"kwrd\">CASE<\/span> activity_id<\/pre>\n<pre class=\"alt\">        <span class=\"kwrd\">WHEN<\/span> @FragmentationHighActivityID <span class=\"kwrd\">THEN<\/span> <span class=\"str\">'GuidHighFragmentation'<\/span><\/pre>\n<pre>        <span class=\"kwrd\">WHEN<\/span> @FragmentationLowActivityID <span class=\"kwrd\">THEN<\/span> <span class=\"str\">'GuidLowFragmentation'<\/span><\/pre>\n<pre class=\"alt\">        <span class=\"kwrd\">ELSE<\/span> <span class=\"str\">'UNKNOWN'<\/span><\/pre>\n<pre>    <span class=\"kwrd\">END<\/span> <span class=\"kwrd\">as<\/span> QueryTable, <\/pre>\n<pre class=\"alt\">    <span class=\"kwrd\">COUNT<\/span>(*) <span class=\"kwrd\">AS<\/span> occurences<\/pre>\n<pre><span class=\"kwrd\">FROM<\/span> FragmentationEffectResultsParsed<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">WHERE<\/span> activity_id <span class=\"kwrd\">IN<\/span> (@FragmentationHighActivityID, @FragmentationLowActivityID)<\/pre>\n<pre>  <span class=\"kwrd\">AND<\/span> event_name <span class=\"kwrd\">IN<\/span> (<span class=\"str\">'async_io_completed'<\/span>, <span class=\"str\">'async_io_requested'<\/span>, <\/pre>\n<pre class=\"alt\">        <span class=\"str\">'file_read'<\/span>, <span class=\"str\">'file_read_completed'<\/span>, <span class=\"str\">'physical_page_read'<\/span>)<\/pre>\n<pre><span class=\"kwrd\">GROUP<\/span> <span class=\"kwrd\">BY<\/span> event_name, activity_id<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">ORDER<\/span> <span class=\"kwrd\">BY<\/span> activity_id, event_name<\/pre>\n<\/p><\/div>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n<\/blockquote>\n<p><a href=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/293e1634\/image.png\" target=\"_blank\"><img fetchpriority=\"high\" decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/4880bd07\/image_thumb.png\" width=\"349\" height=\"215\" \/><\/a><\/p>\n<p>Impressive!&#160; SQL Server had to do ten times the I\/O operations against the fragmented table than it did against the non-fragmented table.&#160; You might notice in the output that the number of physical_page_read events is larger than the number of actual pages in the indexes for the table.&#160; Yes and no, I restricted the output of sys.dm_db_index_physical_stats to just level 0 of the indexes, or the leaf level.&#160; There are two additional levels in the nonclustered indexes being scanned but they only account for nine additional pages for the fragmented index and five additional pages for the non-fragmented index.&#160; The other pages are from the system metadata tables which have to be read by the engine as well, which can be confirmed by reading the parsed event data from the dbo.FragmentationEffectResultsParsed table.<\/p>\n<p>Where the impact really gets interesting is when we take a look at the I\/O sizes for file_read_completed events and aggregate the results based on the table and the I\/O size being read from disk using the same activity_id\u2019s from the previous query for aggregation.<\/p>\n<blockquote>\n<div class=\"csharpcode\">\n<pre class=\"alt\"><span class=\"rem\">-- Aggregate the file_read_completed events by the IO size and table<\/span><\/pre>\n<pre><span class=\"kwrd\">SELECT<\/span><\/pre>\n<pre class=\"alt\">    <span class=\"kwrd\">CASE<\/span> activity_id<\/pre>\n<pre>        <span class=\"kwrd\">WHEN<\/span> @FragmentationHighActivityID <span class=\"kwrd\">THEN<\/span> <span class=\"str\">'GuidHighFragmentation'<\/span><\/pre>\n<pre class=\"alt\">        <span class=\"kwrd\">WHEN<\/span> @FragmentationLowActivityID <span class=\"kwrd\">THEN<\/span> <span class=\"str\">'GuidLowFragmentation'<\/span><\/pre>\n<pre>        <span class=\"kwrd\">ELSE<\/span> <span class=\"str\">'UNKNOWN'<\/span><\/pre>\n<pre class=\"alt\">    <span class=\"kwrd\">END<\/span> <span class=\"kwrd\">as<\/span> QueryTable, <\/pre>\n<pre>    <span class=\"kwrd\">size<\/span>\/1024 <span class=\"kwrd\">as<\/span> read_size_kb, <\/pre>\n<pre class=\"alt\">    <span class=\"kwrd\">size<\/span>\/1024\/8 <span class=\"kwrd\">as<\/span> read_size_pages, <\/pre>\n<pre>    <span class=\"kwrd\">COUNT<\/span>(*) <span class=\"kwrd\">AS<\/span> occurences<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">FROM<\/span> FragmentationEffectResultsParsed<\/pre>\n<pre><span class=\"kwrd\">WHERE<\/span> activity_id <span class=\"kwrd\">IN<\/span> (@FragmentationHighActivityID, @FragmentationLowActivityID)<\/pre>\n<pre class=\"alt\">  <span class=\"kwrd\">AND<\/span> event_name <span class=\"kwrd\">IN<\/span> (<span class=\"str\">'file_read_completed'<\/span>)<\/pre>\n<pre><span class=\"kwrd\">GROUP<\/span> <span class=\"kwrd\">BY<\/span> database_id, file_id, <span class=\"kwrd\">size<\/span>, activity_id<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">ORDER<\/span> <span class=\"kwrd\">BY<\/span> QueryTable, <span class=\"kwrd\">size<\/span> <span class=\"kwrd\">desc<\/span><\/pre>\n<pre>GO<\/pre>\n<\/p><\/div>\n<\/blockquote>\n<p><a href=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/39d61122\/image.png\" target=\"_blank\"><img decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/07060aae\/image_thumb.png\" width=\"413\" height=\"308\" \/><\/a><\/p>\n<p>I suspected that fragmentation would impact the ability of the database engine to do large sequential reads from the table index while scanning it, but I was not expecting the impact to be as bad as it actually was.&#160; I ran this test numerous times to isolate out if it was some kind of a fluke and the results are consistently repeatable within a relatively low margin of change.&#160; The smallest read size for the non-fragmented index was 64KB where the fragmented table did a majority of its I\/O using 64KB reads or smaller.<\/p>\n<p>Now I know what you are thinking, the non-fragmented index in this case is smaller than the fragmented one so it should do less total I\/O.&#160; You\u2019d be right to think that, but keep in mind that they both contain the same number of records, demonstrating the wasted space that Paul talked about in the session at SQL Connections.&#160; However, not to worry, we can fix the non-fragmented table and add additional records to it to push the index size over the size of the fragmented one in page count.<\/p>\n<blockquote>\n<div class=\"csharpcode\">\n<pre class=\"alt\"><span class=\"rem\">-- Add additional data to bring page count higher than the GuidHighFragmentation table!<\/span><\/pre>\n<pre>INSERT <span class=\"kwrd\">INTO<\/span> GuidLowFragmentation (FirstName, LastName)<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">SELECT<\/span> <span class=\"kwrd\">TOP<\/span> 10000<\/pre>\n<pre>    a.name, b.name<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">FROM<\/span> master.dbo.spt_values <span class=\"kwrd\">AS<\/span> a<\/pre>\n<pre><span class=\"kwrd\">CROSS<\/span> <span class=\"kwrd\">JOIN<\/span> master.dbo.spt_values <span class=\"kwrd\">AS<\/span> b<\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">WHERE<\/span> a.name <span class=\"kwrd\">IS<\/span> <span class=\"kwrd\">NOT<\/span> <span class=\"kwrd\">NULL<\/span> <\/pre>\n<pre>    <span class=\"kwrd\">AND<\/span> b.name <span class=\"kwrd\">IS<\/span> <span class=\"kwrd\">NOT<\/span> <span class=\"kwrd\">NULL<\/span><\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">ORDER<\/span> <span class=\"kwrd\">BY<\/span> NEWID()<\/pre>\n<pre><span class=\"kwrd\">GO<\/span> 10<\/pre>\n<pre class=\"alt\">&#160;<\/pre>\n<pre><span class=\"rem\">-- Rebuild the indexes to remove any fragmentation<\/span><\/pre>\n<pre class=\"alt\"><span class=\"kwrd\">ALTER<\/span> <span class=\"kwrd\">INDEX<\/span> <span class=\"kwrd\">ALL<\/span> <span class=\"kwrd\">ON<\/span> GuidLowFragmentation REBUILD<\/pre>\n<pre><span class=\"kwrd\">GO<\/span><\/pre>\n<\/p><\/div>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n<\/blockquote>\n<p>If we go back and rerun our query against sys.dm_db_index_physical_stats the non-fragmented index will have an additional 100000 records and just over 1000 pages.<\/p>\n<p><a href=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/11572f0e\/image.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/7716c5e9\/image_thumb.png\" width=\"644\" height=\"57\" \/><\/a><\/p>\n<p>Now we can delete the files from our original test, execute CHECKPOINT and flush the buffer cache and rerun the tests to see what affect more than double the index pages has on the non-fragmented indexes I\/O operations.<\/p>\n<p><a href=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/7cf16982\/image.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/1c341056\/image_thumb.png\" width=\"351\" height=\"216\" \/><\/a><\/p>\n<p>For the event counts, even with more pages in the index, the non-fragmented table still incurs significantly less I\/O operations.<\/p>\n<p><a href=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/3b76b729\/image.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px\" title=\"image\" border=\"0\" alt=\"image\" src=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/5ab95dfc\/image_thumb.png\" width=\"418\" height=\"330\" \/><\/a><\/p>\n<p>For the I\/O size, the smallest IO performed for the non-fragmented table is still 64KB, and there was a increase in reads at 256KB and 512KB sizes.&#160; <\/p>\n<p>While SSD\u2019s might reduce the IO latency for random read operations, they don\u2019t negate the need to continue to adhere to proper design principals for primary keys, fill factor on indexes, and index maintenance.&#160; The actual runtimes of the two tests were nearly identical, and often flipped back and forth between which one took a few milliseconds longer than the other to complete for this demo.&#160; However, keep in mind that these tables were less than 16MB data total until the non-fragmented table had additional records added to it.&#160; Even at larger data sizes the performance of the two scans will be close enough that the average end user wouldn\u2019t notice the difference, but under the covers the number of I\/O operations being performed is significantly different.&#160; One thing to consider is that an SSD while faster still has an upper limit to the number of I\/O operations per second (IOPS) that it can perform.&#160; Your average database might not be able to push that limit even with heavy fragmentation, but with the cost of SSD\u2019s still at a premium I wouldn\u2019t waste any of what was available if I had them in my server.<\/p>\n<p>So to wrap up, the answer to the question \u201cDoes index fragmentation matter with SSD\u2019s?\u201d&#160; It Depends on if you care about wasting space and wasting I\/O more than anything else, but YES it still matters and it still has an impact.<\/p>\n<p><strong>One note about this post:<\/strong><\/p>\n<p>The demo for this post works with SQL Server 2008 and 2008 R2 with the exception that you don\u2019t get the I\/O size back from the file_read_completed event.&#160; You can still see the impact that fragmentation has on the number of I\/O operations being performed using the demo exactly as provided from this blog post with SQL Server 2008 and 2008 R2.&#160; I chose to go the Denali route because the impact to the I\/O size is quite interesting IMO.<\/p>\n<p>See you on the playground!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Two weeks ago at SQL Connections in Orlando, FL, I got to participate in a session that Paul and Kimberly do at the end of the conference titled, \u201cFollow the Rabbit.\u201d&#160; The premise of the session is that Paul and Kimberly throw a big list of topics up on the screen and anyone in the [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19,23,38,40],"tags":[],"class_list":["post-528","post","type-post","status-publish","format-standard","hentry","category-database-administration","category-extended-events","category-sql-server-2008","category-sql-server-denali"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Does Index Fragmentation Matter with SSD\u2019s? - Jonathan Kehayias<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Does Index Fragmentation Matter with SSD\u2019s? - Jonathan Kehayias\" \/>\n<meta property=\"og:description\" content=\"Two weeks ago at SQL Connections in Orlando, FL, I got to participate in a session that Paul and Kimberly do at the end of the conference titled, \u201cFollow the Rabbit.\u201d&#160; The premise of the session is that Paul and Kimberly throw a big list of topics up on the screen and anyone in the [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/\" \/>\n<meta property=\"og:site_name\" content=\"Jonathan Kehayias\" \/>\n<meta property=\"article:published_time\" content=\"2011-04-13T02:25:41+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-04-13T18:41:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/632d5920\/image_thumb.png\" \/>\n<meta name=\"author\" content=\"Jonathan Kehayias\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jonathan Kehayias\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/\"},\"author\":{\"name\":\"Jonathan Kehayias\",\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/#\\\/schema\\\/person\\\/01c10d94f3648654ef706d5e6305f69c\"},\"headline\":\"Does Index Fragmentation Matter with SSD\u2019s?\",\"datePublished\":\"2011-04-13T02:25:41+00:00\",\"dateModified\":\"2017-04-13T18:41:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/\"},\"wordCount\":1982,\"commentCount\":11,\"image\":{\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.SQLskills.com\\\/blogs\\\/jonathan\\\/wp-content\\\/uploads\\\/windows-live-writer\\\/does-index-fragmentation-matter-with-ssd\\\/632d5920\\\/image_thumb.png\",\"articleSection\":[\"Database Administration\",\"Extended Events\",\"SQL Server 2008\",\"SQL Server Denali\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/\",\"url\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/\",\"name\":\"Does Index Fragmentation Matter with SSD\u2019s? - Jonathan Kehayias\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.SQLskills.com\\\/blogs\\\/jonathan\\\/wp-content\\\/uploads\\\/windows-live-writer\\\/does-index-fragmentation-matter-with-ssd\\\/632d5920\\\/image_thumb.png\",\"datePublished\":\"2011-04-13T02:25:41+00:00\",\"dateModified\":\"2017-04-13T18:41:45+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/#\\\/schema\\\/person\\\/01c10d94f3648654ef706d5e6305f69c\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.SQLskills.com\\\/blogs\\\/jonathan\\\/wp-content\\\/uploads\\\/windows-live-writer\\\/does-index-fragmentation-matter-with-ssd\\\/632d5920\\\/image_thumb.png\",\"contentUrl\":\"https:\\\/\\\/www.SQLskills.com\\\/blogs\\\/jonathan\\\/wp-content\\\/uploads\\\/windows-live-writer\\\/does-index-fragmentation-matter-with-ssd\\\/632d5920\\\/image_thumb.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/does-index-fragmentation-matter-with-ssds\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Database Administration\",\"item\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/category\\\/database-administration\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Does Index Fragmentation Matter with SSD\u2019s?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/#website\",\"url\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/\",\"name\":\"Jonathan Kehayias - The Rambling DBA\",\"description\":\"The Rambling DBA\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.sqlskills.com\\\/blogs\\\/jonathan\\\/#\\\/schema\\\/person\\\/01c10d94f3648654ef706d5e6305f69c\",\"name\":\"Jonathan Kehayias\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/86630e27f5deecc5c393ea57fc7c3b6a068949f4fd6b5309f81de5a276f12855?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/86630e27f5deecc5c393ea57fc7c3b6a068949f4fd6b5309f81de5a276f12855?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/86630e27f5deecc5c393ea57fc7c3b6a068949f4fd6b5309f81de5a276f12855?s=96&d=mm&r=g\",\"caption\":\"Jonathan Kehayias\"},\"sameAs\":[\"http:\\\/\\\/3.209.169.194\\\/blogs\\\/jonathan\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Does Index Fragmentation Matter with SSD\u2019s? - Jonathan Kehayias","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/","og_locale":"en_US","og_type":"article","og_title":"Does Index Fragmentation Matter with SSD\u2019s? - Jonathan Kehayias","og_description":"Two weeks ago at SQL Connections in Orlando, FL, I got to participate in a session that Paul and Kimberly do at the end of the conference titled, \u201cFollow the Rabbit.\u201d&#160; The premise of the session is that Paul and Kimberly throw a big list of topics up on the screen and anyone in the [&hellip;]","og_url":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/","og_site_name":"Jonathan Kehayias","article_published_time":"2011-04-13T02:25:41+00:00","article_modified_time":"2017-04-13T18:41:45+00:00","og_image":[{"url":"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/632d5920\/image_thumb.png","type":"","width":"","height":""}],"author":"Jonathan Kehayias","twitter_misc":{"Written by":"Jonathan Kehayias","Est. reading time":"16 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/#article","isPartOf":{"@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/"},"author":{"name":"Jonathan Kehayias","@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/#\/schema\/person\/01c10d94f3648654ef706d5e6305f69c"},"headline":"Does Index Fragmentation Matter with SSD\u2019s?","datePublished":"2011-04-13T02:25:41+00:00","dateModified":"2017-04-13T18:41:45+00:00","mainEntityOfPage":{"@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/"},"wordCount":1982,"commentCount":11,"image":{"@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/#primaryimage"},"thumbnailUrl":"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/632d5920\/image_thumb.png","articleSection":["Database Administration","Extended Events","SQL Server 2008","SQL Server Denali"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/","url":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/","name":"Does Index Fragmentation Matter with SSD\u2019s? - Jonathan Kehayias","isPartOf":{"@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/#primaryimage"},"image":{"@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/#primaryimage"},"thumbnailUrl":"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/632d5920\/image_thumb.png","datePublished":"2011-04-13T02:25:41+00:00","dateModified":"2017-04-13T18:41:45+00:00","author":{"@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/#\/schema\/person\/01c10d94f3648654ef706d5e6305f69c"},"breadcrumb":{"@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/#primaryimage","url":"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/632d5920\/image_thumb.png","contentUrl":"https:\/\/www.SQLskills.com\/blogs\/jonathan\/wp-content\/uploads\/windows-live-writer\/does-index-fragmentation-matter-with-ssd\/632d5920\/image_thumb.png"},{"@type":"BreadcrumbList","@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/does-index-fragmentation-matter-with-ssds\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/"},{"@type":"ListItem","position":2,"name":"Database Administration","item":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/category\/database-administration\/"},{"@type":"ListItem","position":3,"name":"Does Index Fragmentation Matter with SSD\u2019s?"}]},{"@type":"WebSite","@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/#website","url":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/","name":"Jonathan Kehayias - The Rambling DBA","description":"The Rambling DBA","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/#\/schema\/person\/01c10d94f3648654ef706d5e6305f69c","name":"Jonathan Kehayias","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/86630e27f5deecc5c393ea57fc7c3b6a068949f4fd6b5309f81de5a276f12855?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/86630e27f5deecc5c393ea57fc7c3b6a068949f4fd6b5309f81de5a276f12855?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/86630e27f5deecc5c393ea57fc7c3b6a068949f4fd6b5309f81de5a276f12855?s=96&d=mm&r=g","caption":"Jonathan Kehayias"},"sameAs":["http:\/\/3.209.169.194\/blogs\/jonathan"]}]}},"_links":{"self":[{"href":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/wp-json\/wp\/v2\/posts\/528","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/wp-json\/wp\/v2\/comments?post=528"}],"version-history":[{"count":0,"href":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/wp-json\/wp\/v2\/posts\/528\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/wp-json\/wp\/v2\/media?parent=528"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/wp-json\/wp\/v2\/categories?post=528"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/jonathan\/wp-json\/wp\/v2\/tags?post=528"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}