SQL Server Estimates don't use AVG_RANGE_ROWS for Uniqueidentifer Parameter
2
votes
1
answer
29
views
I'm trying to debug a very weird query row estimation.
The query is very simple. I have a table
OrderItems
that contains for each Order (column OrderId
) the items of the order.
SELECT count(*)
FROM orders.OrderItem
WHERE OrderId = '5a7e53c4-fc70-f011-8dca-000d3a3aa5e1'
According to the statistics from IX_OrderItem_FK_OrderId
(that's just a normal unfiltered foreign key index CREATE INDEX IX_OrderItem_FK_OrderId on orders.OrderId(OrderId)
, the density is 1.2620972E-06 with 7423048 rows, so about ~9.3 items per order (if we ignore the items with OrderId = NULL
, if we include them there are even less).
The statistics are created with FULLSCAN, and are only slightly out of date (around ~0.2% new rows since the last recompute).
| Name | Updated | Rows | Rows Sampled | Steps | Density | Average key length | String Index | Filter Expression | Unfiltered Rows | Persisted Sample Percent |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| IX_OrderItem_FK_OrderId | Aug 3 2025 4:36PM | 7423048 | 7423048 | 198 | 0.1649756 |26.443027 | "NO " | NULL | 7423048 | 100 |
| All density | Average Length | Columns |
| --- | --- | --- |
| 1.2620972E-06 | 10.443027 | OrderId |
| 1.3471555E-07 | 26.443027 | OrderId, Id |
The query plan however expects, that the query returns 205.496 items. And in reality there are actually 0 results - because the orderId
doesn't exist.
Detailed Query Plan:
https://www.brentozar.com/pastetheplan/?id=hVKYNLmXSU
It probably uses the histogram for coming up with the estimate.
It should fall into following bucket with RANGE_HI_KEY = 'a39932d8-aa2c-f011-8b3d-000d3a440098'
. But that estimate should then be 6.87 according to the AVG_RANGE_ROWS.
It somehow looks like it uses the EQ_ROWS from the previous bucket (but 205 might also just be by accident).
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
| --- | --- | --- | --- | --- | --- |
| 9d2e2bea-aa6e-f011-8dca-000d3a3aa5e1 | 12889 | 205 | 2412 | 5.343698 |
| a39932d8-aa2c-f011-8b3d-000d3a440098 | 21923 | 107 | 3191 | 6.8702602 |
OPTION(RECOMPILE)
does not help.
Can somebody explain how SQL Server (in particularly Azure SQL) is coming up with that number?
- Does it really think that the parameter is close enough to the bucket start, and just takes the EQ_ROWS value even though the AVG_RANGE_ROWS is a lot smaller?
- Does it not understand the parameter because it's defined as VARCHAR? If I replace it with DECLARE @OrderId UNIQUEIDENTIFIER = '5a7e...'; WHERE OrderId = @OrderId
the estimate is down to 6. But if that's the reason, from where is the estimate 205?
Asked by Jakube
(121 rep)
Aug 5, 2025, 04:53 PM
Last activity: Aug 6, 2025, 04:39 PM
Last activity: Aug 6, 2025, 04:39 PM