You might want to consider just bringing the statistics up to date for the indexes that have a high level of fragmentation.
Yes, the indexes are fragemented, but they are still indexes and they will still work, regardless of the level of fragmentation.
However, the statistics are possibly not up-to-date until you...
- update the statistics
- rebuild the index
Why? There is a built-in algorithm that determines when to update the statistics. Statistics are updated according to the following documentation:
The Query Optimizer determines when statistics might be out-of-date by counting the number of data modifications since the last statistics update and comparing the number of modifications to a threshold. The threshold is based on the number of rows in the table or indexed view.
References:
- Statistics (Microsoft Docs)
- SQL Server Statistics: Explained (Microsoft Developer Blogs)
The document then goes on to explain the algorithms for SQL Server 2014 and older:
Up to SQL Server 2014, SQL Server uses a threshold based on the percent of rows changed. This is regardless of the number of rows in the table. The threshold is:
- If the table cardinality was 500 or less at the time statistics were evaluated, update for every 500 modifications.
- If the table cardinality was above 500 at the time statistics were evaluated, update for every 500 + 20 percent of modifications.
If you would adapt that to your 2 Million row table, then the statistics would update roughly after 20% changes/rows * 2'000'000 rows = 200'000 changes
on a SQL Server 2014 or older version.
It's slightly different for SQL 2016 and newer:
Starting with SQL Server 2016 and under the database compatibility level 130, SQL Server uses a decreasing, dynamic statistics update threshold that adjusts according to the number of rows in the table. This is calculated as the square root of 1,000 multiplied by the current table cardinality. With this change, statistics on large tables will be updated more often. However, if a database has a compatibility level below 130, then the SQL Server 2014 threshold applies.
References:
- Statistics (Microsoft Docs)
- Running SAP Applications on the Microsoft Platform
If you would adapt that to your 2 Million row table in your SQL Server Azure environment, then the statistics would update roughly after 2% of the data has changed. 2% changes/rows * 2'000'000 rows = 20'000 changes
.
So you could be running into one of these situations:
Situation 1
- not enough changes happening
- statistics outdated
- indexes fragmented
- bad query plan
... bad performance, index fragmentation
Situation 2
- lots of changes happening
- statistics update regularly
- indexes fragmented
- good query plan
... periodically bad performance (statistics updating), index fragmentation resulting in slightly worse performance than when defragmented.
Situation 3
- changes happening irrelevant
- statistics updated or not
- indexes fragmented
- bad or good query plan
... varying performance, index fragmentation resulting in slightly worse performance than when defragmented.
Possible solutions
Update the statistics manually for the indexes on the very large tables to ensure you have up-to-date statistics and query plans that will select the correct index scan/seek options based on the cardinality of the data.
Create the indexes with a FILLFACTOR
of 90, 80 or even lower depending on how often data gets inserted to reduce fragmentation of indexes caused by inserted/modified data.
Turn on the option AUTO_UPDATE_STATS_ASYNC = ON
to decrease the probability of performance impacts due to statistics being updated during peak times of the day.
Considerations
As pointed out by others, index fragmentation "per se" shouldn't be an issue. However, depending on various factors it can be an indication of other issues.
When you rebuild the indexes you are refreshing the statistics and performance is back to normal.
References