服务器重启后首次运行大表查询需要很长时间

Posted

技术标签:

【中文标题】服务器重启后首次运行大表查询需要很长时间【英文标题】:First run of query on big table takes very long after server restart 【发布时间】:2016-07-21 10:21:32 【问题描述】:

在服务器重新启动后,当我运行以下查询时,它需要很长时间。该表有 1.500.000 行,查询返回 140.000 行。

select 
Oid, -- Primary Key 
IsTranslated -- bool(bit) column
from Translation
where [Language] = '24648b4e-05ac-42cb-b6cf-c1167b6a41b7'

语言列上有一个索引。服务器重启后的第一次运行需要 6 分钟才能完成,后续查询需要 1-2 秒才能完成。将“WITH(INDEX(iLanguage_Translation))”添加到查询的 FROM 部分并没有提高性能。

但是在服务器重启后的第一次运行中,follownig 查询只需 2 秒即可完成:

select Oid -- Primary Key
from Translation
where [Language] = '24648b4e-05ac-42cb-b6cf-c1167b6a41b7'

这两个查询之间的唯一区别是一个额外的 bool(bit) 列。为什么传输 140.000 行的额外位列需要 6 分钟?

我有带有 i7 2700K 处理器和 16GB 内存的 SQL Server 2014。

这是表创建脚本:

CREATE TABLE [dbo].[Translation](
    [Oid] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [PropertyName] [nvarchar](max) NULL,
    [DefaultLanguageValue] [nvarchar](max) NULL,
    [TranslatedValue] [nvarchar](max) NULL,
    [IsTranslated] [bit] NULL,
    [NodePath] [nvarchar](max) NULL,
    [Description] [nvarchar](max) NULL,
    [Language] [uniqueidentifier] NULL,
    [OptimisticLockField] [int] NULL,
    [GCRecord] [int] NULL,
 CONSTRAINT [PK_Translation] PRIMARY KEY CLUSTERED 
(
    [Oid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

/****** Object:  Index [iGCRecord_Translation]    Script Date: 2016.07.21. 12:09:08 ******/
CREATE NONCLUSTERED INDEX [iGCRecord_Translation] ON [dbo].[Translation]
(
    [GCRecord] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

/****** Object:  Index [iLanguage_Translation]    Script Date: 2016.07.21. 12:09:08 ******/
CREATE NONCLUSTERED INDEX [iLanguage_Translation] ON [dbo].[Translation]
(
    [Language] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Translation]  WITH NOCHECK ADD  CONSTRAINT [FK_Translation_Language] FOREIGN KEY([Language])
REFERENCES [dbo].[Language] ([Oid])
NOT FOR REPLICATION 
GO

ALTER TABLE [dbo].[Translation] CHECK CONSTRAINT [FK_Translation_Language]
GO

将在我的网络应用程序中使用的最终查询使用表的所有列:

SELECT [Oid]
      ,[PropertyName]
      ,[DefaultLanguageValue]
      ,[TranslatedValue]
      ,[IsTranslated]
      ,[NodePath]
      ,[Description]
      ,[Language]
      ,[OptimisticLockField]
      ,[GCRecord]
  FROM [dbo].[Translation]
  where [Language] = '24648b4e-05ac-42cb-b6cf-c1167b6a41b7'

执行计划:

执行计划 XML:

<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.2" Build="12.0.4459.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="1" StatementEstRows="171288" StatementId="1" StatementOptmLevel="FULL" CardinalityEstimationModelVersion="120" StatementSubTreeCost="102.045" StatementText="SELECT [Oid],[PropertyName],[DefaultLanguageValue],[TranslatedValue],[IsTranslated],[NodePath],[Description],[Language],[OptimisticLockField],[GCRecord] FROM [dbo].[Translation] WHERE [Language]=@1" StatementType="SELECT" QueryHash="0x7722D3C37A4ACDF4" QueryPlanHash="0xEBAED5C218B1FD8D" RetrievedFromCache="false">
          <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
          <QueryPlan DegreeOfParallelism="1" CachedPlanSize="24" CompileTime="475" CompileCPU="2" CompileMemory="184">
            <MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0" />
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="209425" EstimatedPagesCached="104712" EstimatedAvailableDegreeOfParallelism="4" />
            <RelOp AvgRowSize="20181" EstimateCPU="2.07874" EstimateIO="99.9661" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="171288" LogicalOp="Clustered Index Scan" NodeId="0" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="102.045" TableCardinality="1889620">
              <OutputList>
                <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="Oid" />
                <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="PropertyName" />
                <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="DefaultLanguageValue" />
                <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="TranslatedValue" />
                <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="IsTranslated" />
                <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="NodePath" />
                <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="Description" />
                <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="Language" />
                <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="OptimisticLockField" />
                <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="GCRecord" />
              </OutputList>
              <RunTimeInformation>
                <RunTimeCountersPerThread Thread="0" ActualRows="144003" ActualEndOfScans="1" ActualExecutions="1" />
              </RunTimeInformation>
              <IndexScan Ordered="false" ForcedIndex="false" ForceScan="false" NoExpandHint="false" Storage="RowStore">
                <DefinedValues>
                  <DefinedValue>
                    <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="Oid" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="PropertyName" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="DefaultLanguageValue" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="TranslatedValue" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="IsTranslated" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="NodePath" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="Description" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="Language" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="OptimisticLockField" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="GCRecord" />
                  </DefinedValue>
                </DefinedValues>
                <Object Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Index="[PK_Translation]" IndexKind="Clustered" Storage="RowStore" />
                <Predicate>
                  <ScalarOperator ScalarString="[vintocon.archifm.Loc].[dbo].[Translation].[Language]=guid'24648B4E-05AC-42CB-B6CF-C1167B6A41B7'">
                    <Compare CompareOp="EQ">
                      <ScalarOperator>
                        <Identifier>
                          <ColumnReference Database="[vintocon.archifm.Loc]" Schema="[dbo]" Table="[Translation]" Column="Language" />
                        </Identifier>
                      </ScalarOperator>
                      <ScalarOperator>
                        <Const ConstValue="guid'24648B4E-05AC-42CB-B6CF-C1167B6A41B7'" />
                      </ScalarOperator>
                    </Compare>
                  </ScalarOperator>
                </Predicate>
              </IndexScan>
            </RelOp>
            <ParameterList>
              <ColumnReference Column="@1" ParameterCompiledValue="'24648b4e-05ac-42cb-b6cf-c1167b6a41b7'" ParameterRuntimeValue="'24648b4e-05ac-42cb-b6cf-c1167b6a41b7'" />
            </ParameterList>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

【问题讨论】:

我想是关于缓存的。尝试DBCC DROPCLEANBUFFERS 而不是重新启动 - 应该有相同的效果。 我也猜想这是第一次使用页面时缓冲池填满。鉴于您在聚集键是 GUID 的聚集索引中保存了 150 万行,我猜该索引非常分散,这可以解释为什么将所有页面读入内存需要很长时间。 【参考方案1】:

阅读KeyLookup关于执行计划的操作并创建一个覆盖索引:

CREATE NONCLUSTERED INDEX [iLanguage_Translation]
    ON [dbo].[Translation] ([Language]) INCLUDE (IsTranslated)

【讨论】:

问题是在我的最终查询中我需要select中的所有列,而varchar(max)列不能用作索引 在您的问题中,我看不到任何最终查询...请更新您的问题并提供实际执行计划 更新问题

以上是关于服务器重启后首次运行大表查询需要很长时间的主要内容,如果未能解决你的问题,请参考以下文章

Linux多久需要重启一次?长时间不重启会出现啥后果?

MySQL 服务器上非常简单的 AVG() 聚合查询需要很长时间

MySQL 查询返回 JSON 数据需要很长时间

与下次运行相比,sql 查询需要很长时间

为啥这个查询需要这么长时间?

在 MYSQL 表上选择查询需要很长时间并超时