【问题标题】:Sql Query is 20 times slower when adding where clause on Row_number() value row在 Row_number() 值行上添加 where 子句时,Sql Query 慢 20 倍
【发布时间】:2015-12-17 10:51:46
【问题描述】:

这是对全文查询的简单搜索

WITH xx AS
( 
    SELECT   
        kh.* ,
        ROW_NUMBER() OVER ( ORDER BY kh.Id ) AS RowNo
    FROM     
        KhachHang kh
    WHERE    
        CONTAINS (kh.Ten, 'hoang and van and ngan')
        AND kh.TrangThai = 1
)
SELECT xx.* 
FROM xx

只有在添加Where 子句时才会出现问题

WITH xx AS
( 
    SELECT   
        kh.* ,
        ROW_NUMBER() OVER ( ORDER BY kh.Id ) AS RowNo
    FROM     
        KhachHang kh
    WHERE    
        CONTAINS (kh.Ten, 'hoang and van and ngan')
        AND kh.TrangThai = 1
)
SELECT xx.* 
FROM xx
--- This is key that create the difference       
WHERE xx.RowNo > 0 AND xx.RowNo <= 100

这种差异使后一个查询的运行速度慢了大约 20 倍。

我检查了执行计划并注意到 Index Seek 和 Scan 之间的区别。但即使我用 WITH FORCESEEK 更改了后者,结果也是相似的。

我的生产数据库中有 800 万条记录。

Attached execution plan

非常感谢任何帮助和建议。

【问题讨论】:

  • 您的选择,将其放入临时表并在 RowNo 列上建立索引,您应该做的第一件事
  • 感谢@Veljko89。你的建议确实解决了问题。但是您将其添加为评论,因此我无法提出答案。
  • 很好……很高兴能帮上忙。祝你未来好运

标签: sql sql-server full-text-search


【解决方案1】:

尝试使用临时表而不是 CTE。因此,将整个表或几个字段放在临时表中,然后在临时表上进行行号搜索。

如果表有一个 pk,那么只需将 pk 和 rowno 放入临时表中,确定您需要的 rowno 范围,然后返回父级以获取详细信息。

如果你发现性能仍然很差,你可以在临时表的 rowno 列上添加一个非聚集索引(在你填充它之后)。

【讨论】:

  • 您的建议确实提高了性能。它希望你能给出一些详细的解释为什么?谢谢。
  • 没有看到很难说的计划,一种可能性是 CTE 可能在内存中,即它将获得高内存授权,以便 CTE 在执行行时将行保存在内存中数运算。而临时表位于磁盘上,因此需要更少的内存。运行 cte 并通过实际执行计划检查内存授予时,值得关注页面预期寿命
猜你喜欢
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 2014-03-12
  • 2014-02-14
  • 1970-01-01
  • 1970-01-01
  • 2020-12-30
相关资源
最近更新 更多