当我这样做时dbcc show_statistics ('Reports_Documents', PK_Reports_Documents)
,报告ID 18698会得到以下结果:
对于此查询:
SELECT *
FROM Reports_Documents
WHERE ReportID = 18698 option (recompile)
我得到一个查询计划,该计划使聚簇索引PK_Reports_Documents
按预期进行。
但是令我感到困惑的是估计行数的错误值:
根据此:
当示例查询WHERE子句值等于直方图RANGE_HI_KEY值时,SQL Server将使用直方图中的EQ_ROWS列来确定等于的行数。
这也是我期望的样子,但是在现实生活中情况并非如此。我还尝试RANGE_HI_KEY
了由提供的直方图中存在的其他一些值,show_statistics
并经历了相同的情况。就我而言,此问题似乎导致某些查询使用非常不理想的执行计划,导致执行时间为几分钟,而我可以通过查询提示使其在1秒内运行。
总而言之:有人可以解释一下为什么EQ_ROWS
直方图中的行数不用于估计行数以及不正确的估计值来自何处吗?
更多(可能有帮助)的信息:
- 自动创建统计信息已打开,并且所有统计信息都是最新的。
- 正在查询的表大约有8000万行。
PK_Reports_Documents
是由ReportID INT
和组成的组合PKDocumentID CHAR(8)
该查询似乎总共加载了5个不同的统计对象,所有这些对象都包含ReportID
+表中的其他一些列。它们都已全新更新。RANGE_HI_KEY
下表中的是直方图中最高的上限列值。
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
| name | stats_id | auto_created | user_created | Leading column Type | RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
| PK_Reports_Documents | 1 | 0 | 0 | Stationary | 18722 | 0 | 2228,526 | 0 | 1 |
| _dta_index_Reports_Documents_42_1629248859__K1_K63_K14_K13_K22_K23_72_6 | 62 | 0 | 0 | Stationary | 18698 | 0 | 2228,526 | 0 | 1 |
| _dta_stat_1629248859_1_1_59 | 76 | 0 | 1 | Stationary | 18686 | 50,56393 | 1 | 0 | 13397,04 |
| _dta_stat_1629248859_1_22_14_18_12_6 | 95 | 0 | 1 | Stationary | 18698 | 0 | 2228,526 | 0 | 1 |
| _dta_stat_1629248859_1_7_14_4_23_62 | 96 | 0 | 1 | Stationary | 18698 | 56,63327 | 21641,5 | 0 | 14526,44 |
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
sp_updatestats
计划每天晚上运行以更新统计信息。
_dta_
统计信息,自从我第一次查看数据库以来就一直在那里。我不知道使用建议可能会产生这样的不利影响……