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

时间:2008-12-22 17:22:37

标签: sql sql-server-2005 performance

SQL Server 2005

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

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

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

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

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

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

6 个答案:

答案 0 :(得分:10)

SELECT TOP 1000 x, y, z, COUNT(*) OVER () AS TotalCount
FROM dbo.table

答案 1 :(得分:5)

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

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

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

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

答案 2 :(得分:3)

您想使用“计数”和分组依据,请查看此参考:http://msdn.microsoft.com/en-us/library/ms175997.aspx

此外,您的问题似乎发布在此处:http://www.eggheadcafe.com/software/aspnet/32427870/select-top-n-plus-a-count.aspx

祝你好运

答案 3 :(得分:0)

您可能过高估计了“前1000名”的表现优势,特别是如果总成绩只有5000左右。

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

这里有两个选项:

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

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

答案 4 :(得分: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。

答案 5 :(得分:-2)

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

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

规则。

是的,执行两个查询(一个计数,一个选择*)不是最佳解决方案(您可以在一个查询中执行此操作!)。但是,如果肯定你将会成为一个瓶颈?

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

写得快,写得更好,简介,然后写得最好。

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

相关问题