sql-server - 为每个父级选择前 1 条记录时,子查询太慢

标签 sql-server performance sql-server-2008-r2 database-performance

我试图使用子查询方法找到所选日期内的最后一条记录。问题是查询速度太慢。我想知道是否有人对如何重写此查询以提高性能有任何想法。我的服务器因此而崩溃。
为了使测试更容易,我创建了一个表变量来生成用于测试目的的假数据。要测试此脚本,请运行 usp_ExtractData'400000'

我关心的是 ---B 部分 我的结果是 18 秒处理 400000*3 = 1200000 条记录。在真实的数据库上,我对其进行索引并每晚重新索引。

--Store proceedure with table variable data

ALTER PROCEDURE [dbo].[usp_ExtractData](
@TotalRecord int--Create random records for each product
)

AS
BEGIN
    --MS SQL 2008
    SET NOCOUNT ON;

    --SECTION 1--Create test data--- GO TO SECTION 2
        --Create Variable table to Products fake data
        DECLARE @Product TABLE
        (
          ProductID int primary  key not null
          ,SKU varchar(100) not null
        )
        --Insert couple records into @Product table
        INSERT INTO @Product(ProductID, SKU) VALUES     (100,'CUP100')
        INSERT INTO @Product(ProductID, SKU) VALUES     (101,'CUP101')
        INSERT INTO @Product(ProductID, SKU) VALUES     (102,'MUG101')

        --Create Variable table to hold Products History data
        DECLARE @History TABLE
        (
           ID int identity not null
          ,ProductID int not null
          ,VisitedDatetime datetime not null
        )

        --Generate random record for testing
        WHILE @TotalRecord>0
            BEGIN
                INSERT INTO  @History( ProductID, VisitedDatetime) VALUES (100,DATEADD(minute,rand()*100,GETDATE()))
                INSERT INTO  @History( ProductID, VisitedDatetime) VALUES (101,DATEADD(minute,rand()*100,GETDATE()))
                INSERT INTO  @History( ProductID, VisitedDatetime) VALUES (102,DATEADD(minute,rand()*100,GETDATE()))
                set @TotalRecord=@TotalRecord-1
            END
    --SECTION 1--Finised creating test data



    ---SECTION B 

      --SELECTION B1- SEE DATA
      SELECT * FROM @History         ORDER BY ProductID, VisitedDatetime DESC
        --Run query to find the last visit per each ProductID

        --THIS IS TOO SLOW
        DECLARE @TestPerformanceDatetime datetime--Test performance
        SET @TestPerformanceDatetime= GETDATE()
        SELECT  *, (select top(1) VisitedDatetime FROM @History as t2 WHERE t2.ProductID=ProductID and VisitedDatetime BETWEEN GETDATE() AND GETDATE()+10 ORDER BY VisitedDatetime DESC) as LastVistiDate
        FROM     @Product

        --Display the performance
        SELECT  DATEDIFF(SECOND, @TestPerformanceDatetime,getdate()) AS TotalSeconds
    ---SECTION B - End
END

最佳答案

使用交叉应用max()

select *
from @Product p
cross apply (
    select MAX(VisitedDatetime) LastVisitedDatetime
    from @History
    where VisitedDatetime BETWEEN GETDATE() AND GETDATE()+10
        and ProductID = p.ProductID
) h

关于sql-server - 为每个父级选择前 1 条记录时,子查询太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12116345/

相关文章:

sql - 我如何连接我的数据集中的字段?

iphone - iPhone 启动缓慢

sql-server - FxCop for SQL Server - 分析 SQL Server 数据库潜在问题的工具

sql-server - 如果我们可以直接基于 RAW 表构建 View ,则需要 OLAP 多维数据集

sql - 将多个队列链接到 SQL 服务代理中的同一服务

mysql - 通过映射表(Sql)获取映射列名

MATLAB - 'webread' 由于内容类型检查而变慢?

java - 将变量声明为最终的内部方法会提高性能吗?

sql-server - SQL Server 中的 ALL 与 ANY 评估

sql - 使用 Nolock 提示更新查询