因此,用户表有4000万行。如果我没有WHERE子句,下面的查询将足够快地运行(不到1秒) 如果将WHERE子句放在查询中,则大约需要10分钟才能返回结果集。 我在UserType列上添加了一个索引,但是由于某种原因,它似乎并未影响响应时间
CREATE INDEX idx_users_user_type ON Users (UserType);
查询:
SELECT TOP 100
*
FROM Users u
INNER JOIN Company c ON c.ID = u.CompanyID
INNER JOIN Location l ON l.ID = u.LocationId
WHERE
u.UserType = 'manager'
UserType只有3个值:
manager
employee
temp
如果可能的话,我不想将列更改为INT值,因为ETL流程会将数据导入到现在很难更改的表中。
答案 0 :(得分:5)
首先,您应该在不使用TOP
的情况下使用ORDER BY
来阅读this article。简短的版本是您不能保证每次运行的结果都一样,除非您有ORDER BY
。
由于SQL Server只需对 first 100行执行TABLE SCAN,因此第一个查询运行很快。简单。现在,您添加了WHERE
子句... SQL Server必须找到该谓词为true的所有行。当然,您有一个索引,这可以有所帮助。 SQL Server将(或可能)使用该索引,但是如果使用了该索引,则它将必须进行键查找来检索其余的列(因为您SELECT *
)。因此,它需要做更多的工作。很有可能甚至没有使用索引,因为SQL Server可以决定仅执行TABLE SCAN来检查每一行的谓词,而不是进行键查找,这样更快。当然,这意味着您必须读取4000万行(检查表的大小...这需要进入内存。我敢打赌它已分页到磁盘上,甚至是spilling to TEMPDB)。
因此,它当然会变慢...您正在针对4000万行检查条件,而不是提取 random TOP 100
。如果您需要有关所有DDL(创建表,创建索引)语句的进一步帮助,we need the execution plans at a minimum。
要探索的其他选项是:
答案 1 :(得分:1)
您可以添加索引:
CREATE INDEX idx_users_user_type_company_id_location_id
ON Users (CompanyId, LocationId,UserType);