Sql 优化排名查询

Sql 优化排名查询,sql,sql-server,Sql,Sql Server,我正在使用此查询从Sql Server DB获取用户的排名: select user_rank from (select t.user_id, rank() over (order by score desc) as user_rank from user_stats t ) t where t.user_id='some_user_id'; 该表包含大约22000行,查询耗时3.5秒,速度太慢 此表中有几个索引,它们是相关的: 用户id-唯一的非聚集索引 分数-非唯一、非聚集索引 如果

我正在使用此查询从Sql Server DB获取用户的排名:

select user_rank
from (select t.user_id, rank() over (order by score desc) as user_rank
  from user_stats t
 ) t
where t.user_id='some_user_id';
该表包含大约22000行,查询耗时3.5秒,速度太慢

此表中有几个索引,它们是相关的:

用户id-唯一的非聚集索引

分数-非唯一、非聚集索引

如果我更改查询并使用id(这是我的主键)而不是user_id,则查询将快速执行:

select user_rank
from (select t.id, rank() over (order by score desc) as user_rank
  from user_stats t
 ) t
where t.id='some_id';
检查执行计划后,我发现聚集索引扫描成本为92%,尽管我真的不明白为什么在这种情况下需要它

如何优化此查询

查询的统计信息:

SQL Server解析和编译时间:CPU时间=0毫秒,运行时间= 0毫秒

SQL Server执行时间:CPU时间=0毫秒,运行时间=0毫秒。 SQL Server解析和编译时间:CPU时间=0毫秒,运行时间= 0毫秒

SQL Server执行时间:CPU时间=0毫秒,运行时间=0毫秒。 SQL Server解析和编译时间:CPU时间=0毫秒,运行时间= 0毫秒

SQL Server执行时间:CPU时间=0毫秒,运行时间=0毫秒。 SQL Server解析和编译时间:CPU时间=0毫秒,运行时间= 0毫秒

(1行受影响)表“用户统计”。扫描计数1,逻辑 读取22529,物理读取0,预读读取0,lob逻辑读取 0,lob物理读取0,lob预读读取0

(1行受影响)

SQL Server执行时间:CPU时间=78毫秒,运行时间=3576 ms.SQL Server解析和编译时间:CPU时间=0毫秒,已用时间 时间=0毫秒

SQL Server执行时间:CPU时间=0毫秒,运行时间=0毫秒


我怀疑性能下降的主要原因是索引没有覆盖。你可能会看到,通过指数覆盖,业绩有了实质性的改善。是一篇讨论覆盖索引的好文章

简而言之,索引只提供了一个指向该行的指针。为了获得“score”列的数据(这是对结果集进行排序所必需的),引擎必须扫描聚集索引以查找数据。如果在索引中包含该值,则引擎将能够执行该操作,而无需进行聚集索引扫描

索引应重写如下:

在USER_STATS(USER_ID)INCLUDE(score)上创建唯一的非聚集索引UQ_USER_STATS_USER_ID

而不是

select user_rank
from (select t.id, rank() over (order by score desc) as user_rank
  from user_stats t
 ) t
where t.id='some_id';
那怎么办

with t as (
  select t.user_id, 
  ROW_NUMBER() as user_rank
  from user_stats t
  order by score desc
)
select user_rank
from t
where t.id='some_id';

不管发生什么,您都将在这里进行扫描,因为子查询必须查看表中的每一行。不确定为什么会是3.5秒,但没有表和索引定义,这只是猜测。如果UserID是唯一的,那么对一个用户进行排名的目的是什么?但是为什么使用user_id和id两者都进行索引时会有这样的区别呢?@GiorgiNakeuri-我在一个存储过程中使用此查询,该过程返回特定用户的排名user@UdiI,UserID在user\u stats表中是唯一的吗?它将返回你1行,不是吗?