3

我在Patient&Person表中有 200,000 行,显示的查询需要 30 秒才能执行。

我已经在表中定义了主键(和聚集Person索引)。我还能在这里做些什么来提高我的程序的性能?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  
4

2 回答 2

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

除此之外,您应该在包含您加入/过滤的列的索引的表上创建索引。

因此,例如,我将在表 Patient 上创建一个索引,其中包含列 (TenantId,PersonId,ResponsiblePersonId,AddedBy) 并包含列 (PatientId,PatientIdentifier)

于 2013-03-27T06:58:00.090 回答
0

坦率地说,200,000 行对 SQL Server 来说不算什么。

请先去掉逻辑冗余,比如你有主键,为什么还要分组这么多列,为什么需要加入同一张表(人)3次?

去除逻辑冗余后,至少需要创建一些复合索引/包含索引。获取执行计划 (CTRL+M) 或 (CTRL+M),看看你错过了什么索引。如果您需要进一步的帮助,请使用几行示例数据粘贴您的表架构。

于 2013-03-27T07:07:45.097 回答