【问题标题】:Paging through Large table in sql 2005sql 2005中的大表分页
【发布时间】:2009-06-09 23:22:05
【问题描述】:

我有一个包含 15 列和 650 万条记录的表。 我需要在分页的帮助下从 C# 端访问此表。我已经编写了一个 SP,但检索数据大约需要 1.30 分钟。 这是我的存储过程 -

Create Proc demo
(
@startRowIndex int,
@maximumRows int
)
AS

DECLARE @first_id int, @startRow int

SET @startRowIndex =  (@startRowIndex - 1)  * @maximumRows

IF @startRowIndex = 0 
SET @startRowIndex = 1

SET ROWCOUNT @startRowIndex

SELECT @first_id = RecordID FROM edd_business_listings_05282009 ORDER BY RecordID

PRINT @first_id

SET ROWCOUNT @maximumRows

SELECT * FROM edd_business_listings_05282009 WHERE 
RecordID >= @first_id 
ORDER BY RecordID

SET ROWCOUNT 0

有谁知道让这个运行更快的方法。

【问题讨论】:

  • 如果没有表定义(请创建表)、键和索引,我们只会猜测。并不是说这曾经阻止过这里的任何人......
  • RecordID 上的非聚集索引,即使它已经是聚集索引,也有助于 SELECT @first_id = RecordID ....
  • 如果 RecordID 是连续的,聚集索引会更好。
  • 聚集索引对于最终的 SELECT 来说效果很好,但对于初始 SELECT,非聚集索引需要更少的 I/O。
  • 谁将翻阅 650 万条记录?

标签: c# sql-server paging


【解决方案1】:

您的应用程序可以发送最后一个 RecordID 吗?

让前端工作更加努力。

创建 Proc 演示 (@startRowID int, @maximumRows int) AS

SET ROWCOUNT @maximumRows

SELECT * FROM edd_business_listings_05282009 WHERE RecordID > @startRowID ORDER BY RecordID

设置行计数 0

【讨论】:

  • @jfar: SET ROWCOUNT @maximumRows 确保它将返回所有 20 个后续行(如果存在)。没有?
  • 对,SET ROWCOUNT 不会受到缺失记录的影响。
【解决方案2】:

尝试在 SQL 2005 中使用 ROW_NUMBER:http://www.4guysfromrolla.com/webtech/010406-1.shtml

这样的程序会有所帮助:

CREATE PROCEDURE dbo.GetListingPaged
(
    @StartRowIndex int,
    @MaximumRows int
)
AS
    SELECT
        RecordID,
        Field2 -- Not *
    FROM
    (
    SELECT
        RecordID,
        Field2 -- Not *
        ROW_NUMBER() OVER (ORDER BY RecordID) AS RowRank
    FROM edd_business_listings_05282009
    ) AS ListingWithRowNumbers
    WHERE
        RowRank > @StartRowIndex
    AND
        RowRank <= (@StartRowIndex + @MaximumRows)

GO

【讨论】:

  • 我想看看这种方法的响应时间与分页深度。
【解决方案3】:

好的,当然,这也是我的猜测:

Create Proc demo ( @startRowIndex int, @maximumRows int ) AS
DECLARE @first_id int, @startRow int
SET @startRowIndex = (@startRowIndex - 1) * @maximumRows

IF @startRowIndex = 0 SET @startRowIndex = 1

SELECT TOP (@maximuRows)
 {'all columns except N'}
 FROM (
    Select *, ROW_NUMBER() Over(Order by RecordID) as N
     from edd_business_listings_05282009
    ) As t
 WHERE N >= @startRowIndex
 ORDER BY RecordID

【讨论】:

    【解决方案4】:

    最好的解决方案很大程度上取决于

    1.数据变化的频率

    2.sproc 被调用的频率以及用户对页面的典型化深度和

    3.在最新的订单中您可以接受多少延迟(如果有)。

    通常在网站后端,您的用户只使用前几页,但 google bot 可以猛击您的深层页面,从而猛击您的 CPU。通常只支持这种实时排序到某个点(例如,对前几百或几千行使用 row_number() )然后切换到在某个时间间隔内(可能每小时)刷新的非规范化排序列表。

    【讨论】:

      【解决方案5】:

      尝试在 RecordId 列上放置一个索引。我认为正在发生的是您在行数到位之前进行整个表扫描,以便 Sql 可以订购所有内容。如果你已经有一个索引而不是其他的东西是问题所在。我对记录数是两倍的表执行了相同的查询,并且我的执行时间从未超过 2 秒。

      从技术上讲,使用 ROWCOUNT 或 Row_Number() 应该在性能方面完成同样的事情,但我会使用 Row_Number(),因为它是一种更现代的方法,并且设置 rowcount 比我的 Row_Number() 复杂得多进不去。

      【讨论】:

        【解决方案6】:

        如果你使用SQL Server 2005,那么你可以试试

        SELECT  field1, field2, fieldN
        FROM     (SELECT ROW_NUMBER() OVER (ORDER BY RecordID) AS Row,
                     field1, field2, fieldN FROM edd_business_listings_05282009)
                    AS ListingsWithRowNumbers
        WHERE  Row >= @startRowIndex AND Row <= @startRowIndex + @maximumRows
        

        但无论如何,请尝试重新考虑这种架构。在 UI 中显示数百万条记录(甚至分页)有什么用?您可以尝试限制记录数并最初只查询一个子集...

        【讨论】:

        • 一旦@startRowIndex > @maximumRows,这将无法通过记录的第一页。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-05
        • 1970-01-01
        • 1970-01-01
        • 2011-01-27
        • 1970-01-01
        • 2016-10-09
        相关资源
        最近更新 更多