如何在SQL中正确进行服务器分页?

时间:2014-08-22 07:57:16

标签: sql sql-server

我的情况:我的申请很慢。它变得很慢......主要是因为我感觉我的dataTables / grid的服务器分页被错误地实现了。

让我们开始吧:

  • 我有一个SQL Server 2008数据库,一个包含所有信息的表,其中有10列,目前是19K行

  • 我的应用程序基于JavaScript和ASP.Net后端代码。

我的SQL查询是:

WITH Ordered AS 
(
    SELECT *, ROW_NUMBER() OVER (ORDER BY Created DESC) AS 'RowNumber'
      FROM Meetings
     WHERE State IN ('Appointed', 'Accepted')
       AND [xxx] LIKE '%1%'
       AND [yyy] LIKE '%2%'
) 
SELECT * 
  FROM Ordered
 WHERE RowNumber BETWEEN 1 AND 41;

所以目前此查询运行大约27到32秒,这意味着超过30秒我得到超时...在1年内19k行...这意味着在1个月内最新的每个查询将对死。 ..

据我所知,此查询的顺序是问题:此处没有完成索引。 因为查询首先排序,然后用手动行号选择所有,然后只选择40 ...(当然在我的网格的第2页上它得到第41行到第81行......)

COULD 在我的“Created desc”上做一个索引,查询会快得多, BUT 每列都可以对我的网格进行排序,这意味着“创建了desc” “可能是我桌上的每个其他列,当然还有desc和asc order!

那么,如何改进呢?

//编辑:

很抱歉忘记:

内部查询(内部选择)运行6秒,而总查询运行31秒...... 这意味着“WITH ORDERES AS”就是问题所在!

1 个答案:

答案 0 :(得分:2)

首先要做的事情是:您遇到了性能问题,采用适当的方法并采取适当的措施。 内部查询(内部选择)运行6秒,而总查询运行31秒......这意味着...... 是业余主义。请阅读How to analyse SQL Server performance以了解衡量效果的正确方法。在我们继续之前,如果你从6秒开始,你已经输掉了比赛。

现在,回答这个问题。

WHERE State in('Appointed','Accepted') AND  [xxx] LIKE '%1%' AND [yyy] LIKE '%2%'

此表达式基本上是不可索引的。即使你在State上添加一个索引,它也无济于事,因为它的基数较低(每个行的行数很少)。并且like '% ... %'是无法索引的,因为它会在文本中间搜索值。

您可以尝试将like '% ... %'替换为CONTAINS ...这样的全文搜索,这将更快,您可以搜索特定的足够条款。但它确实需要您正确部署和配置full-text indexes

至于分页,我不太赞同ROWNUMBER方法。即使存在排序列,它也会涉及扫描和计数以跳过行数,并在您转到更高页面时变得越来越慢。我更推荐基于密钥的方法:

SELECT TOP (page size) ...
WHERE keys > <last row>
ORDER BY...

但这种方法更难实现,因为它需要跟踪而不是页码。

但期待没有奇迹。您要求关系OLTP系统执行ElasticSearch / Solr的工作。它永远不会像你期望的那样工作。使用适合作业的工具(搜索引擎)。另请阅读Dynamic Search Conditions in T‑SQL进行更全面的讨论,但同样,不要期待奇迹。