选择前1000名,但知道有多少行?

问题描述 投票:3回答:6

SQL Server 2005

我在DB中有1000万行,并运行一个select(有很多“where”和关节......非常复杂)。结果以网格形式呈现(想想goolge结果),因此,用户不可能使用超过1000个结果。

所以我用一个TOP 1000来限制我的SQL。

问题:用户仍然想知道他的搜索有5432个结果。

我是否可以在不付出代价的情况下获得该信息(换句话说,仍然获得“前1000名”给我的速度优势?)

假设 - 假设TOP 1000在100K行中带来1000个。因此即使是移动100K的网络价格也可能是一个问题。

结论没有免费的午餐!你可以得到优雅的方式(接受的答案),但它仍然需要更昂贵的操作(即计算所有结果)。在现实生活中,我将使用2 SQL方法,一个返回前1000行进行显示,一个是ASYNC,并使用count(*)结果更新一些AJAX面板,这将花费更长的时间到计算机

sql sql-server-2005 performance
6个回答
10
投票
SELECT TOP 1000 x, y, z, COUNT(*) OVER () AS TotalCount
FROM dbo.table

5
投票

就个人而言,我会选择两个声明来访问数据库。一个用于检索计数,一个用于检索前1000个记录。

您可以批量运行两个查询,通过保存数据库的往返来挤出一些额外的性能。

-- Get the count
select count(*) from table where [criteria]

-- Get the data
select [cols] from table where [criteria]

3
投票

你想使用“计数”和分组,看看这个参考:http://msdn.microsoft.com/en-us/library/ms175997.aspx

你的问题似乎也贴在这里:http://www.eggheadcafe.com/software/aspnet/32427870/select-top-n-plus-a-count.aspx

祝好运


0
投票

您可能过高估计了“前1000名”的性能优势,特别是如果总共只有大约5000个。

服务器已经必须完成所有连接和填充(这通常是困难的部分),然后必须按照您指定的方式对结果集进行排序,然后最终获得1000个第一个结果。

这里有两个选择:

1)使用Count(*)执行一次查询以获取结果计数,然后使用前1000次执行第二次查询,检索相应的列(如Neil建议的那样)。要么 2)第一次检索所有行,将它们缓存在结果集中,然后仅向用户显示1000行。

听起来第一个会更快,但第二个只需要打一次数据库,并且根据数据库和查询的具体情况,可能会更好(只要数据库不会返回100,000行! )


0
投票

由于您使用的是SQL Server 2005,因此您可以使用CTE进行此类查询。这是我目前为客户做的事情:

;WITH Search_Results AS
(
     SELECT TOP(@system_max_rows)
          my_column1,
          my_column2,
          ROW_NUMBER() OVER
          (
               ORDER BY
                    -- Your order criteria here
          ) AS row_num,
          COUNT(my_column1) OVER (PARTITION BY '') As total_count
     FROM
          My_Table
     -- Put any joins here
     WHERE
          -- Put WHERE criteria here
)
SELECT
     my_column1,
     my_column2,
     row_num,
     total_count
FROM
     Search_Results
WHERE
     ((row_num - 1)/@rows_per_page) + 1 = CASE
                WHEN ((total_count - 1)/@rows_per_page) + 1 < @page_number THEN ((total_count - 1)/@rows_per_page) + 1
                ELSE @page_number
           END
OPTION (RECOMPILE)

重新编译就在那里,因为搜索条件可能会在对存储过程的调用之间发生巨大变化,从而导致缓存的查询计划变坏。希望参数/变量是显而易见的。这是一个分页搜索解决方案。系统max rows变量是硬编码的,因此即使应用程序也无法覆盖可返回的最大行数并使服务器崩溃。要获得前1000名,您将传入@page_number = 1和@rows_per_page = 1000。


-2
投票

这不会回答你的问题,但我认为这是一个很好的案例,我们实施:

  • 硬件很便宜
  • 程序员并不便宜

规则。

是的,做两个查询(一个计数,一个选择*)不是最佳解决方案(您可以在一个查询中执行!)。但你有多确定这会成为一个瓶颈?

我对这些问题感到困惑,我必须自己记住这个问题才能继续发展。

写得快,写得更好,PROFILE,然后写得最好。

或者,这可能是瓶颈,这也是你问的原因。但在我看来,如果它是你的瓶颈,更好的优化将重组数据库,以便简化您的查询本身。

© www.soinside.com 2019 - 2024. All rights reserved.