我应该从多少返回的记录开始预期性能问题?

时间:2010-01-27 17:43:58

标签: sql sql-server sql-server-2005

我有一个查询,我已经调整了一段时间,但我似乎无法将执行时间缩短很多。在执行计划中,一切看起来都在做它应该做的事情,没有与查询的任何特定部分相关的大量成本,一切都在使用索引查找它应该在哪里。当我针对不同的客户端运行相同的查询时,它运行得相当快,但只返回150k记录。当我为我最大的客户端运行它时,它返回600k记录并花费超过十分钟。

我的问题可能是因为我正在返回的记录数量很难获得良好的性能,或者上面描述的内容是否在SQL Server的能力范围内?

10 个答案:

答案 0 :(得分:6)

可能是行。但更有可能的是,生成4倍以上数据的客户端在其他区域的数据库上的活动量也增加了4倍。这意味着内存使用量增加4倍,磁盘数量增加4倍,锁定量增加4倍。确保硬件分配正确。

但继续前进,我试图想象一下,对于返回600K记录甚至150K记录的查询,您可以做些什么有用的工作。我假设这些从未向最终用户显示,因为即使是分页太多而且无用。如果没有,我们需要考虑如何使用这些数据。

如果这是一个批处理过程,也许10分钟就完全没问题了,没有理由花费你宝贵的时间进一步处理它。如果它与其他查询结合使用,可能需要尽快引入该查询中的元素,以保持结果集更小。

答案 1 :(得分:3)

除了记录数量之外,两个系统之间还有什么不同之处:

  • 可用于SQL的RAM
  • CPU核心
  • IO配置(RAID中的主轴数,RAID类型,LUN配置)
  • IO路径(逻辑和物理磁盘的布局,数据库mdf / ndf / ldf文件的位置)
  • 索引碎片
  • 加载SQL Server
  • 在主机上加载

比较SET STATISTICS IO ON的两个位置时:

  • 与150k位置相比,600k的IO大约是x4倍吗?那么时差可以完全归因于硬件的差异。
  • 逻辑IO计数是否为x4次,但物理IO计数差异很大?然后你有一个RAM问题(不足以将数据库缓存在内存中)。
  • 物理IO的数量是否接近预期的x4倍,但时间差异很大?然后你可能正在处理碎片。
  • IO的数量是否与预期的x4次显着不同?然后你有一个不同的计划可能由非常不同的基数和估计驱动。

当然,这些是在黑暗中没有适当数据来支持它们的狂野镜头。认为他们是一个猜测,而不是一个权威的解决方案。

答案 2 :(得分:1)

您需要首先确定实际查询所花费的时间,然后您可以确定将整个600K行返回到客户端所花费的时间(您可能不应该这样做)。假设每行数据都是100字节,那么您将向客户端返回60MB。那将是痛苦的。

答案 3 :(得分:1)

  

我应该从多少返回的记录开始预期性能问题?

一个人。

此查询:

SELECT  COUNT(*)
FROM    myreallybigtable 

将只返回一条记录,但您可能需要等待数小时才能完成。

客户端 - 服务器I/O(可能是唯一依赖依赖返回记录的数量和大小的东西)通常是最不重要的因素之一。

真正重要的是查询计划,它指定了基础表中的记录访问,转换和返回的方式和顺序。

因此,正如其他人所建议的那样,只需在此处发布您的查询,我们就可以告诉您如何优化它。

答案 4 :(得分:1)

查看您的IO统计信息:

Table 'RefStuExitCatg'. Scan count 1, logical reads 22810 ...
Table 'RefEngLangArtsTestProfcy'. Scan count 1, logical reads 22810 ... 
Table 'RefEngLangAcqstnStatSt'. Scan count 1, logical reads 22810 ...

VS

Table 'RefStuExitCatg'. Scan count 1, logical reads 1514532, ...  
Table 'RefEngLangArtsTestProfcy'. Scan count 1, logical reads 1514532,...
Table 'RefEngLangAcqstnStatSt'. Scan count 1, logical reads 1514532, ...

快速查询必须在所有“Ref ...”表上阅读22810页。相比之下,慢查询必须读取1514532页。这是1.5M对22k, 66次更多。因此,您的慢速数据库的方式,方式,数据大小差异大于您知道的150k和600k行。我想说这是对差异的一个非常好的解释。

答案 5 :(得分:0)

您是否通过索引调整向导运行查询?即使您已经在使用索引,其他索引(尤其是复合索引)仍有可能提高性能。

将查询分解为具有临时表的部分也可能会改进。

我们在报告系统中运行查询,这些查询通常返回300,000条记录,连接20个表,其中包含许多共同相关的子查询,并获得亚秒响应时间。

答案 6 :(得分:0)

好吧支撑自己.... 这是我继承的原始存储过程。如果您想看到我所做的更改,请告诉我。

带有“--HERE”注释的部分是真正的性能问题开始的地方。

ALTER PROCEDURE [dbo].MyProc
@LEAESIID int,
@AcademicYear varchar(10),
@ReportType varchar(16),
@SchoolESIID varchar(max),
-- 
@Grade varchar(8000),
@Gender varchar(8000),
@Race varchar(8000),
--
@AsOfDate datetime,
--
@UserID int
AS

create table #TempSchool
(
    SchoolESIID int
)
Create table #TempRace
(
    Race varchar(60)
)

declare @CALPADSSnpshtKey int
select @CALPADSSnpshtKey = 
    CALPADSSnpshtKey 
    from vwCertSnpshtRptngSnpsht cs2
    Where 
    -- Filter to correct snapshot
        rtrim(ltrim(cs2.AcdmcYearCode)) = rtrim(ltrim(@AcademicYear)) AND
        rtrim(ltrim(cs2.LEARptngEsiId)) in (select rtrim(ltrim(ParsedValue)) from dbo.tfnParseStringIntoTable(@LEAESIID, ',')) AND
        rtrim(ltrim(cs2.RptngTypeCode)) = rtrim(ltrim(@ReportType)) 

Insert into #TempSchool
select ParsedValue from dbo.tfnParseStringIntoTable(@SchoolESIID, ',')  
Insert into #TempRace
select ParsedValue from dbo.tfnParseStringIntoTable(@Race, ',') 

/*
Select query to pull back data from the reporting views.
Since this report is based around enrollment information, the primary table will be StuEnrlmt.
*/
declare 
    @UserLevel nVarchar(10),
    @ESILEAList nvarchar(max),
    @ESISchoolList nvarchar(max)

-- added by jackson chan 090109
-- program
    create table #tmpProgramSet (
        StuKey int
        , CALPADSSnpshtKey int
        , TitleIPartCMigrantFlag char(1)
        , SocioEconomicallyDisadvantagedFlag char(1)
        , SpecialEducationFlag char(1)
        , GiftedAndTalentedFlag char(1)
    )

    insert into #tmpProgramSet
    select se.StuKey,
        se.CALPADSSnpshtKey ,
        max(isnull(case sp.EduPgmCode
            when '135' then 'Y'
            else 'N'
        end, 'N')) as TitleIPartCMigrantFlag,
        max(case
            when 
                isnull(sp.EduPgmCode, 000) = 175 OR
                isnull(s.HighstEduLvlCode, 0) = 14
            then 'Y' 
            else 'N'
        end ) as SocioEconomicallyDisadvantagedFlag,
        max(isnull(case sp.EduPgmCode
            when '144' then 'Y'
            else 'N'
        end, 'N')) as SpecialEducationFlag,
        max(isnull(case sp.EduPgmCode
            when '127' then 'Y'
            else 'N'
        end, 'N')) as GiftedAndTalentedFlag
    from    dbo.vwStuEnrlmtRptngSnpsht se inner join 
            dbo.vwStuRptngSnpsht s on 
                se.StuKey = s.StuKey and
                se.CALPADSSnpshtKey = s.CALPADSSnpshtKey 
                inner join #TempSchool schl2 on 
                se.SchlAtndncEsiID = schl2.SchoolESIID   and
                se.LEARptngESIID = @LEAESIID left outer join
            dbo.vwStuPgmRptngSnpsht sp on 
                se.StuKey = sp.StuKey and
                se.CALPADSSnpshtKey = sp.CALPADSSnpshtKey
        group by se.StuKey, se.CALPADSSnpshtKey 
        order by se.StuKey;

--HERE
    Select distinct
        se.LEARptngEsiID,
        se.SchlAtndncEsiID  as SchlAtndncEsiID,
        se.SchlAtndncCDSCode as SchlAtndncCode,
        se.SchlAtndncName as SchlAtndncName,
        se.SchlAtndncType as SchlAtndncType,
        se.StuKey,
        s.StuIDStwdCal,
        isnull(s.StuLastOrSrnmLgl,'') + ', ' + isnull(s.StuFstNameLgl,'') + ' ' + isnull(s.StuMdlNameLgl,'') as StudentName,
        se.StuIDLcl,
        s.GndrCode,
        isnull(case
                when s.StuHspncEnctyIndctr = 'Y' then 'Hispanic'
                when s.StuEnctyMsngIndctr = 'Y' or s.StuRaceMsngIndctr = 'Y' then 'Missing'
                when s.EthnicityRaceCode2 is not null then 'Multiple' -- if a second race is populated,then Multiple
                else s.EthnicityRaceCode1
        end, 'Missing') as RaceEnthnicity,
        se.GrdLvlCode,
        isnull(
            case s.EngLangAcqstnStatStCode
                when 'EL' then 'Y'
                else 'N'
            end, 'N') as EnglishLearner,
        isnull(
            case
            when 
                -- if a value is null, set it to any value that will evaluate to false in the expression
                -- only students with valid information should be counted as Title III Eligible Immigrants
            -- disabled by jackson chan 12/08/09. Per defect 1605, Student Birth Country Special Circumstance Indicator is not a required field anymore
                --isnull(s.StuIneligSnorImgrntIndctr, 'Y') = 'N' AND
                isnull(s.StuEnrldUSSchlLessThanThreCumltvYrsIndctr, 'N') = 'Y' AND
                isnull(s.CntryCode, 'US') != 'US' AND
                isnull(se.EnrlmtStatCode, '0') = '10' AND
                -- Calculate age from birth date
                isnull(case 
                when datepart(month, s.StuBirDate) < datepart(month, getdate())
                    then datediff(year, s.StuBirDate, getdate())
                when datepart(month, s.StuBirDate) = datepart(month, getdate()) and datepart(day, s.StuBirDate) <= datepart(day, getdate()) 
                    then datediff(year, s.StuBirDate, getdate())
                else datediff(year, s.StuBirDate, getdate()) -1
                end , 0) between 3 and 21 AND
                isnull(se.GrdLvlCode, 'AD') != 'AD'
            then 'Y'
            else 'N'
            end, 'N') as TitleIIIEligibleImmigrantFlag,
        sp.SocioEconomicallyDisadvantagedFlag,
        isnull(case when s.EngLangAcqstnStatStCode in ('EL', 'RFEP')  AND s.EngLangArtsTestProfcyCode = 'N' then 'Y'
            else 'N'
        end, 'N') as LimitedEnglishProficientFlag,
        sp.TitleIPartCMigrantFlag,
        sp.SpecialEducationFlag,
        sp.GiftedAndTalentedFlag
    From 
        dbo.vwStuEnrlmtRptngSnpsht se
        inner join dbo.vwStuRptngSnpsht s on 
            se.StuKey = s.StuKey and
            se.CALPADSSnpshtKey = s.CALPADSSnpshtKey
        left join #tmpProgramSet sp on 
            se.StuKey = sp.StuKey and
            se.CALPADSSnpshtKey = sp.CALPADSSnpshtKey
        inner join #TempSchool schl on 
            se.SchlAtndncEsiID = schl.SchoolESIID   and
            se.LEARptngESIID = @LEAESIID
        inner join #TempRace r on 
            isnull(case
                when s.StuHspncEnctyIndctr = 'Y' then 'Hispanic'
                when s.StuEnctyMsngIndctr = 'Y' or s.StuRaceMsngIndctr = 'Y' then 'Missing'
                when s.EthnicityRaceCode2 is not null then 'Multiple' -- if a second race is populated,then Multiple
                else s.EthnicityRaceCode1
            end, 'Missing') = r.Race 
    Where
        -- Enrollments
        se.StuEsiRltnspExpctdSchlStartDate <= @AsOfDate AND (se.WithdrlDate is null OR se.WithdrlDate >= @AsOfDate) AND
        se.EnrlmtStatCode = '10' AND
        se.StuExitCatgCode != 'N470' AND -- no shows are not considered in active enrollment numbers
        -- Filter to correct snapshot
        se.CALPADSSnpshtKey = @CALPADSSnpshtKey AND
        -- User selection filters
        rtrim(ltrim(se.GrdLvlCode))                       in (select rtrim(ltrim(ParsedValue)) from dbo.tfnParseStringIntoTable(@Grade, ',')) AND
        rtrim(ltrim(s.GndrCode))                              in (select rtrim(ltrim(ParsedValue)) from dbo.tfnParseStringIntoTable(@Gender, ',')) 

答案 7 :(得分:0)

尝试在临时表上放置索引,看看是否有帮助。

答案 8 :(得分:0)

以下是在合理的时间内完成的查询的IO统计信息:

Table '#tmpProgramSet_0000000017E2'. Scan count 11405, logical reads 36450, physical reads 0, read-ahead reads 61, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'RefStuExitCatg'. Scan count 1, logical reads 22810, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'RefEngLangArtsTestProfcy'. Scan count 1, logical reads 22810, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'RefEngLangAcqstnStatSt'. Scan count 1, logical reads 22810, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table '#TempRace_0000000017E1'. Scan count 1, logical reads 11405, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table '#TempSchool_0000000017E0'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'stu'. Scan count 10939, logical reads 47465, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table '#68CACE20'. Scan count 1, logical reads 13814, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'RefEductlSrvcInstn'. Scan count 1, logical reads 448, physical reads 0, read-ahead reads 372, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'RefEnrlmtStat'. Scan count 1, logical reads 27628, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'StuEnrlmt'. Scan count 2, logical reads 141994, physical reads 60, read-ahead reads 200, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'RefGrdLvl'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table '#4D22B3AB'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'RefGndr'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'RefCntryCode'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'RefRace'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'RefFedEnctyRaceCatg'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

以及我长时间运行的查询

Table '#tmpProgramSet_0000000017F5'. Scan count 757266, logical reads 2418742, physical reads 0, read-ahead reads 158, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'RefStuExitCatg'. Scan count 1, logical reads 1514532, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'RefEngLangArtsTestProfcy'. Scan count 1, logical reads 1514532, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'RefEngLangAcqstnStatSt'. Scan count 1, logical reads 1514532, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#TempRace__0000000017F4'. Scan count 1, logical reads 757266, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#TempSchool__0000000017F3'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'stu'. Scan count 586229, logical reads 2711554, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#065B3107'. Scan count 1, logical reads 637919, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'RefEductlSrvcInstn'. Scan count 1, logical reads 448, physical reads 0, read-ahead reads 332, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'RefEnrlmtStat'. Scan count 1, logical reads 1276828, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'StuEnrlmt'. Scan count 2, logical reads 2692331, physical reads 1386, read-ahead reads 97737, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'RefGrdLvl'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#780D11B0'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'RefGndr'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'RefCntryCode'. Scan count 1, logical reads 4, physical reads 1, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'RefRace'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'RefFedEnctyRaceCatg'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

答案 9 :(得分:0)

您是否考虑过两个站点的数据库物理设计? 有可能,具有大型DB的客户端将较旧的数据存储在较慢的磁盘上,并且 可能是慢慢运行查询的原因..