【问题标题】:Unexpected estimated rows in query execution plan (Sql Server 2000)查询执行计划中的意外估计行 (Sql Server 2000)
【发布时间】:2010-12-01 14:56:13
【问题描述】:

如果我运行这个查询

select user from largetable where largetable.user = 1155 

(请注意,我查询用户只是为了将其简化为最简单的情况)

再看执行计划,计划了一次index seek [largetable has an index on user],估计行数是正确的29。

如果我这样做了

select user from largetable where largetable.user = (select user from users where externalid = 100)

[当我硬编码时,子查询的结果是单个值 1155,就像上面一样]

查询优化器估计结果中有 117,000 行。 largetable 中大约有 6,000,000 行,users 中有 1700 行。当我运行查询时,我当然会返回正确的 29 行,尽管估计的行数很大。

我已在相关索引的两个表上使用全扫描更新了统计信息,当我查看统计信息时,它们似乎是正确的。

值得注意的是,对于任何给定用户,largetable 中的行数不超过 3000 行。

那么,为什么估计的执行计划会显示如此大量的估计行?优化器不应该根据统计信息知道它正在寻找具有 29 个对应行的结果,或者即使它不知道子查询将选择哪个用户,它也应该寻找一个 MAXIMUM 为 3,000 行的结果?为什么会有这么大的估计?问题是,这个大估计会影响更大查询中的另一个连接以进行扫描而不是搜索。如果我使用子查询运行较大的查询,则需要 1 分 40 秒。如果使用 1155 硬编码运行它需要 2 秒。这对我来说很不寻常......

谢谢,

克里斯

【问题讨论】:

    标签: sql-server performance sql-execution-plan


    【解决方案1】:

    优化器尽其所能,但统计数据和行数估计仅能做到这一点(如您所见)。

    我假设您的更复杂的查询不能轻易地重写为没有子查询的连接。如果可以的话,你应该先尝试一下。

    如果做不到这一点,是时候利用您对数据性质的额外知识来帮助优化器hints。具体查看index 提示中的forceseek 选项。请注意,如果您的数据稍后发生更改,这可能会很糟糕,因此请注意。

    【讨论】:

    • forceseek 仅适用于 2008 年。 OP 是 2000 年。
    • 啊,没想到。不久前迁移了 2000,所以我没有任何东西可以测试它。 :(
    • 谢谢唐尼;当我重写为连接时,我得到了同样的效果。我不认为SS 2000 有forceseek,但是,我会检查一下..
    • 糟糕,看到有人同意我的观点。我通过执行 addnl 查询来获得子查询结果,然后进入主查询来解决这个问题。但是,我真的很奇怪为什么优化器会这样做!
    • @Querylous - 在“Microsoft SQL Server 2005 内部:查询调整和优化”的第 226 页上,如果您有副本,则特别提到此方法...
    【解决方案2】:

    你试过了吗?

    SELECT lt.user
    FROM Users u
         INNER JOIN largeTable lt
            ON u.User = lt.User
    WHERE u.externalId = 100
    

    请看这个:subqueries-vs-joins

    【讨论】:

    • 是的,而且,重写为连接也有同样的问题!
    猜你喜欢
    • 1970-01-01
    • 2020-04-30
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 2011-01-25
    相关资源
    最近更新 更多