【发布时间】:2014-02-25 20:55:36
【问题描述】:
我有这张桌子:
TopScores
Username char(255)
Score int
DateAdded datetime2
会有很多行。
我对它运行以下查询(存储过程的代码)以获得前 5 名高分者,以及特定用户名的分数,前面是他们正上方的人和下面的人:
WITH Rankings
AS (SELECT Row_Number() OVER (ORDER BY Score DESC, DateAdded DESC) AS Pos,
--if score same, latest date higher
Username,
Score
FROM TopScores)
SELECT TOP 5 Pos,
Username,
Score
FROM Rankings
UNION ALL
SELECT Pos,
Username,
Score
FROM Rankings
WHERE Pos BETWEEN (SELECT Pos
FROM Rankings
WHERE Username = @User) - 1 AND (SELECT Pos
FROM Rankings
WHERE Username = @User) + 1
我必须为表建立索引,所以我首先添加了集群:ci_TopScores(Username) 和非集群:nci_TopScores(Dateadded, Score)。
查询计划显示集群被完全忽略(在我创建非集群之前,我测试过它并被查询使用),并且逻辑读取更多(与没有任何索引的表扫描相比)。
排序是成本最高的运算符。所以我将索引调整为聚集的:ci_TopScores(Score desc, Dateadded desc) 和非聚集的:nci_TopScores(Username)。
仍然排序成本相同。非集群:nci_TopScores(Username) 再次被完全忽略。
如何有效避免对这张表进行排序和索引的高成本?
【问题讨论】:
-
旁注:使用
char(255)非常低效 - 它总是 使用 255 个字节 - 无论您存储多少个字符 - 即使是NULL也使用 255 个字符!任何长度超过 3-5 个字符的字符串都应存储为Varchar(n) -
谢谢。我会通知餐桌上的人。
标签: tsql indexing sql-server-2012 sql-execution-plan