【问题标题】:Indexing to reduce cost of SORT索引以降低 SORT 的成本
【发布时间】: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


【解决方案1】:

CTE 不使用用户名,因此它不使用该索引也就不足为奇了。

CTE 只是语法。您正在评估该 CTE 4 次。

尝试#temp,这样它只会被评估一次。
但是您需要考虑索引。
我会跳过 RowNumber 并在 #temp 上放一个 iden pk 作为 pos
我会跳过 #temp 上的任何其他索引

对于 TopScores,Score desc、DateAdded desc、Username asc 上的索引会有所帮助
但是如果是零散的就无济于事了
那是插入时会分片的索引

insert into #temp (Score, DateAdded, Username)   
select Score, DateAdded, Username
 from TopScores
order by Score desc, DateAdded desc, Username asc  

select top 5 * 
  from #temp 
 order by pos 
union 
select three.* 
from #temp 
join #temp as three
  on #temp.UserName = @user 
 and abs(three.pos - #temp.pos) <= 1

如果对#temp UserName 进行表扫描怎么办。
一次扫描不需要创建一个索引。
无论如何,该索引将严重分散。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-04
    • 1970-01-01
    • 2022-01-16
    • 2022-01-14
    • 2022-01-14
    • 2012-08-03
    • 2015-03-04
    • 1970-01-01
    相关资源
    最近更新 更多