查询执行计划中的意外估计行(Sql Server 2000)

时间:2010-12-01 14:56:14

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

如果我运行此查询

select user from largetable where largetable.user = 1155 

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

查看执行计划,计划索引查找[largetable有一个用户索引],估计的行是正确的29。

但如果我这样做

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

[当我对其进行硬编码时,子查询的结果就像单个值1155一样]

查询优化器估计结果中有117,000行。大型表中有大约6,000,000行,用户中有1700行。当我运行查询当然,尽管有大量的估计行,我仍然会返回正确的29行。

我在相关索引的两个表上更新了fullscan的统计数据,当我查看统计数据时,它们似乎是正确的。

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

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

谢谢,

克里斯

2 个答案:

答案 0 :(得分:1)

优化器尽其所能,但统计数据和行数估计只能到目前为止(正如您所见)。

我假设你的更复杂的查询很容易被重写为没有子查询的连接。如果可以的话,你应该先尝试。

如果做不到这一点,您可以利用关于数据性质的其他知识来帮助优化器hints。具体来看forceseek提示中的index选项。请注意,如果您的数据稍后更改,这可能会很糟糕,因此请注意。

答案 1 :(得分:0)

你试过这个吗?

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

请参阅:subqueries-vs-joins