【问题标题】:Can I retrieve paged rows and total count within a single query?我可以在单个查询中检索分页行和总数吗?
【发布时间】:2017-12-22 14:57:55
【问题描述】:

我有一个在我的网络应用程序中启用了分页的基本网格。该网格由 SQL 数据通过使用 Dapper 的 Web API 填充。在我的 API 控制器中,我正在运行两个单独的查询:一个用于提取行(显示在我的网格中),另一个用于获取记录总数(显示在我的分页控件中)。这有效。但是,我正在尝试优化我的查询。

我的第一个查询,提取行,一次只返回 50 行(使用OFFSETFETCH,提供分页:

SELECT DISTINCT T_INDEX.* 
FROM T_INDEX
INNER JOIN T_INDEXCALLER ON T_INDEX.IndexId = T_INDEXCALLER.IndexId
WHERE... --a fairly complex WHERE statement
ORDER BY CallTime DESC
OFFSET (@offset) ROWS FETCH NEXT 50 ROWS ONLY

我的第二个查询提取所有行的计数,但使用相同的表、相同的连接和相同的 WHERE 子句:

SELECT COUNT(DISTINCT T_INDEX.IndexId)
FROM T_INDEX
INNER JOIN T_INDEXCALLER ON T_INDEX.IndexId = T_INDEXCALLER.IndexId
WHERE... --the same fairly complex WHERE statement

正如我所说,这行得通。每次查询大约需要 2.5 秒,总共需要 5+ 秒。无论如何,时间延迟并不是世界末日,但我想把时间减半。

我想知道是否有任何方法可以检索 50 行检索一个查询中所有行的总数。我意识到这两个查询正在做两件不同的事情。但我的想法是“可能”有一种方法可以调整这两个查询并将它们组合成一个,因为表、连接和 WHERE 子句在两者之间是相同的。

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    你可以试试这个查询:

    SELECT *
    FROM (
       SELECT *, COUNT(*) OVER () AS cnt
       FROM (
          SELECT DISTINCT T_INDEX.*, 
          FROM T_INDEX
          INNER JOIN T_INDEXCALLER ON T_INDEX.IndexId = T_INDEXCALLER.IndexId
          WHERE... --a fairly complex WHERE statement
       ) AS t1 ) AS t2
    ORDER BY CallTime DESC
    OFFSET (@offset) ROWS FETCH NEXT 50 ROWS ONLY
    

    您可以根据确定结果集中不同记录的因素来简化上述查询。

    【讨论】:

    • 我想这可能就是我想要的。在我的第一次尝试中,它似乎工作得很好。我要做更多的调整。
    【解决方案2】:
    SELECT DISTINCT T_INDEX.*,
            (SELECT COUNT(DISTINCT T_INDEX.IndexId)  FROM T_INDEX
               INNER JOIN T_INDEXCALLER ON T_INDEX.IndexId = 
               T_INDEXCALLER.IndexIdAS) AS  TotalCount
    FROM T_INDEX
    INNER JOIN T_INDEXCALLER ON T_INDEX.IndexId = T_INDEXCALLER.IndexId
    WHERE... --a fairly complex WHERE statement
    ORDER BY CallTime DESC
    OFFSET (@offset) ROWS FETCH NEXT 50 ROWS ONLY
    

    【讨论】:

    • 嗯,耐人寻味。但我得到1 为每一行的TotalCount
    • 您到底需要什么?正如你问的总记录
    • 记录总数。与整个数据集的总记录一样。
    【解决方案3】:

    我提出另一种解决方案:不要盲目优化

    你只是想碰碰运气——这是不合理的。

    它们不会做同样的事情,因此它们可能会被单独优化。但更重要的是,您的两个查询都执行了2.5 秒,这对于仅具有简单连接和获取50 recordscount all 的简单任务的查询来说看起来很奇怪。我知道这取决于表的大小和服务器的硬件,但仍然如此。

    所以我认为您可以同时优化它们,而无需将它们“合并”为一个。

    我会先看看查询执行计划。我很确定它可以大大加快速度。因此,请将查询计划添加到您的问题中。

    但即使没有疑问,我也已经有一些问题:

    • 为什么是distinct
    • T_INDEX.CallTime 上有索引吗?

    【讨论】:

    • 感谢您的反馈。是的,我确信有一种方法可以使用其他方法优化我的查询。可以说,这是在黑暗中拍摄的。为了回答您的问题,我使用distinct,因为我的查询中加入了。那里是一对多的关系,我正在检索父行,其中任何子行都与 where 子句匹配。我想要父行的计数,而不是子行。
    • 我在T_INDEX.CallTime 上没有索引。我会尝试添加。
    • 为了使事情更复杂,我正在对子行执行伪全文搜索(使用二进制排序规则),这是我想知道我是否只能查询一次以获得什么的主要原因我需要。 T_INDEXCALLER 中有大约 100 万行。
    猜你喜欢
    • 2020-07-24
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 2017-05-12
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多