3

我在Patient & Person表中有200,000行,查询显示需要30秒才能执行。查询处理200000条记录的速度非常慢

我已经在表中PersonIdPatientIdPatient表中定义了主键(和聚簇索引)。我还可以在这里做什么来提高我的程序的性能?

数据库开发方面的新手。我只知道基本的SQL。也不确定SQL Server能够快速处理200,000行。

全动态过程,你可以在https://github.com/Padayappa/SQLProblem/blob/master/Performance

任何人看到处理面临这样巨大的行?我该如何提高绩效?

DECLARE @return_value int, 
     @unitRows bigint, 
     @unitPages int, 
     @TenantId int, 
     @unitItems int, 
     @page int 
SET @TenantId = 1 
SET @unitItems = 20 
SET @page = 1 

DECLARE @PatientSearch TABLE(
    [PatientId] [bigint] NOT NULL, 
    [PatientIdentifier] [nvarchar](50) NULL, 
    [PersonNumber] [nvarchar](20) NULL, 
    [FirstName] [nvarchar](100) NOT NULL, 
    [LastName] [nvarchar](100) NOT NULL, 
    [ResFirstName] [nvarchar](100) NOT NULL, 
    [ResLastName] [nvarchar](100) NOT NULL, 
    [AddFirstName] [nvarchar](100) NOT NULL, 
    [AddLastName] [nvarchar](100) NOT NULL, 
    [Address] [nvarchar](255) NULL, 
    [City] [nvarchar](50) NULL, 
    [State] [nvarchar](50) NULL, 
    [ZipCode] [nvarchar](20) NULL, 
    [Country] [nvarchar](50) NULL, 
    [RowNumber] [bigint] NULL 
    ) 

    INSERT INTO @PatientSearch SELECT PAT.PatientId 
    ,PAT.PatientIdentifier  
    ,PER.PersonNumber 
    ,PER.FirstName 
    ,PER.LastName 
    ,RES_PER.FirstName AS ResFirstName 
    ,RES_PER.LastName AS ResLastName 
    ,ADD_PER.FirstName AS AddFirstName 
    ,ADD_PER.LastName AS AddLastName 
    ,PER.Address 
    ,PER.City 
    ,PER.State 
    ,PER.ZipCode 
    ,PER.Country 
    ,ROW_NUMBER() OVER (ORDER BY PAT.PatientId DESC) AS RowNumber 
    FROM dbo.Patient AS PAT 
    INNER JOIN dbo.Person AS PER 
    ON PAT.PersonId = PER.PersonId 
    INNER JOIN dbo.Person AS RES_PER 
      ON PAT.ResponsiblePersonId = RES_PER.PersonId 
    INNER JOIN dbo.Person AS ADD_PER 
      ON PAT.AddedBy = ADD_PER.PersonId 
    INNER JOIN dbo.Booking AS B 
      ON PAT.PatientId = B.PatientId 

    WHERE PAT.TenantId = @TenantId AND B.CategoryId = @CategoryId 

    GROUP BY PAT.PatientId 
    ,PAT.PatientIdentifier  
    ,PER.PersonNumber 
    ,PER.FirstName 
    ,PER.LastName 
    ,RES_PER.FirstName 
    ,RES_PER.LastName 
    ,ADD_PER.FirstName 
    ,ADD_PER.LastName 
    ,PER.Address 
    ,PER.City 
    ,PER.State 
    ,PER.ZipCode 
    ,PER.Country  

    ; 

    SELECT @unitRows = @@ROWCOUNT 
    ,@unitPages = (@unitRows/@unitItems) + 1; 

    SELECT * 
    FROM @PatientSearch AS IT 
    WHERE RowNumber BETWEEN (@page - 1) * @unitItems + 1 AND @unitItems * @page 
+0

你插入你的表变量有多少行?您最好创建一个实际的临时表('#PatientSearch')。原因在于查询优化器总是会假定一个表变量只有一行(它缺少任何统计信息),因此如果将大量行插入表变量 – 2013-03-27 07:00:05

+0

@marc_s,它实际上会插入所有200000行为空搜索:( – Billa 2013-03-27 07:01:13

+0

***为什么***你需要将所有200'000行复制到临时表中才能开始?不能只在实际数据上定义一个CTE,并添加' ROW_NUMBER()'函数,并用它来选择你的数据 – 2013-03-27 07:02:44

回答

3

好了,除非我失去了一些东西(如重复行?),你应该能够去除GROUP BY

GROUP BY PAT.PatientId 
    ,PAT.PatientIdentifier  
    ,PER.PersonNumber 
    ,PER.FirstName 
    ,PER.LastName 
    ,RES_PER.FirstName 
    ,RES_PER.LastName 
    ,ADD_PER.FirstName 
    ,ADD_PER.LastName 
    ,PER.Address 
    ,PER.City 
    ,PER.State 
    ,PER.ZipCode 
    ,PER.Country  

因为你是在选择列表中的所有字段分组,和你分区除PAT.PatientId

此外,您应该create index在索引中包含您加入/过滤的列的表。

因此,例如,我会创建

+0

我有一个重复的记录,因为病人有更多的没有预订。我现在更新了我的查询。它是一个动态搜索查询。请检查 – Billa 2013-03-27 07:03:02

+0

整个过程是在https://github.com/Padayappa/SQLProblem/blob/master/Performance – Billa 2013-03-27 07:10:08

+0

'CREATE非聚集索引IX_NC_PatientSearch ON dbo.Patient(TenantId,PERSONID,ResponsiblePersonId,AddedBy) 包括:(PatientId,PatientIdentifier )'产生相同的结果。现在它又增加了5秒:( – Billa 2013-03-27 08:25:31

0

老实说与包含的列(PatientId,PatientIdentifier)列(TenantId,PERSONID,ResponsiblePersonId,AddedBy)上表患者索引,200,000行没什么到SQL Server。

请首先删除逻辑冗余,就像你有主键一样,为什么还要组这么多列,为什么你需要加入同一个表(人)3次?

删除逻辑冗余后,您至少需要创建一些复合索引/包含索引。获取执行计划(CTRL + M)或(CTRL + M),查看错过的索引。如果您需要进一步的帮助,请将表格模式粘贴几行样本数据。

+0

1 join给我Patient First Name,2 join for添加人名First,3rd加入负责任的医生名字 – Billa 2013-03-27 07:09:03