统计信息是最新的,但估计不正确


12

当我这样做时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 计划每天晚上运行以更新统计信息。

Answers:


10

有一个简单的解决方案:

删除所有_dta_...统计信息并停止盲目应用DTA建议。

更多信息

特殊的问题是该列有多组统计信息。额外的dta统计信息是通过对数据进行采样(与索引无关的统计信息的默认行为)创建的。

与抽样统计数据一样,结果直方图并没有覆盖全部数据。问题中的查询碰巧选择了一个超出直方图的值,从而得出了1行的估算值。

没有完全记录当同一列存在多个统计信息集时查询优化器的确切行为。与抽样相比,它确实更喜欢“完全扫描”统计信息,但与较旧的统计信息相比,它也更喜欢更新的统计信息。


这确实有效。但是我没有创建_dta_统计信息,自从我第一次查看数据库以来就一直在那里。我不知道使用建议可能会产生这样的不利影响……
user1151923 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.