インデックススプールの強制


14

パフォーマンス上の理由で避けるべきものを知っていますが、表示されないようにする方法のデモとして表示される状態を表示しようとしています。

ただし、インデックスが欠落しているという警告が表示されますが、オプティマイザーは一時インデックスを作成しないことを選択します。

私が使用しているクエリは

SELECT 
    z.a
FROM dbo.t5 AS z WITH(INDEX(0))
WHERE 
    EXISTS 
    (
        SELECT y.a 
        FROM dbo.t4 AS y
        WHERE y.a = z.a
    )
OPTION (MAXDOP 1);

テーブルスキーマは次のとおりです。

CREATE TABLE dbo.t4
(
    a   integer NULL,
    b   varchar(1000) NULL,
    p   varchar(100) NULL
);

CREATE TABLE dbo.t5
(
    a   integer NULL,
    b   varchar(1000) NULL
);

CREATE UNIQUE CLUSTERED INDEX c1 
ON dbo.t5 (a);

両方のテーブルには10,000行あり、次のようにシミュレートできます。

UPDATE STATISTICS dbo.t4 
WITH 
    ROWCOUNT = 10000, 
    PAGECOUNT = 1000;

UPDATE STATISTICS dbo.t5 
WITH 
    ROWCOUNT = 10000,
    PAGECOUNT = 1000;

クエリプランは次のとおりです。

デフォルトプラン

<?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="11.0.2218.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="1" StatementEstRows="5532.16" StatementId="1" StatementOptmLevel="FULL" StatementOptmEarlyAbortReason="GoodEnoughPlanFound" StatementSubTreeCost="0.407384" StatementText="select a from t5  z WITH(INDEX(0))  where exists (select a from t4 where a=z.a )" StatementType="SELECT" QueryHash="0x1B882FCEA34AEAF4" QueryPlanHash="0x1B276DC04B718F7C" RetrievedFromCache="true">
          <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" MemoryGrant="2912" CachedPlanSize="32" CompileTime="10" CompileCPU="10" CompileMemory="296">
            <MissingIndexes>
              <MissingIndexGroup Impact="82.4536">
                <MissingIndex Database="[planoper]" Schema="[dbo]" Table="[t4]">
                  <ColumnGroup Usage="EQUALITY">
                    <Column Name="[a]" ColumnId="1" />
                  </ColumnGroup>
                </MissingIndex>
              </MissingIndexGroup>
            </MissingIndexes>
            <MemoryGrantInfo SerialRequiredMemory="1024" SerialDesiredMemory="2912" RequiredMemory="1024" DesiredMemory="2912" RequestedMemory="2912" GrantWaitTime="0" GrantedMemory="2912" MaxUsedMemory="896" />
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="104846" EstimatedPagesCached="11834" EstimatedAvailableDegreeOfParallelism="2" />
            <RelOp AvgRowSize="11" EstimateCPU="0.228447" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="5532.16" LogicalOp="Left Semi Join" NodeId="0" Parallel="false" PhysicalOp="Hash Match" EstimatedTotalSubtreeCost="0.407384">
              <OutputList>
                <ColumnReference Database="[planoper]" Schema="[dbo]" Table="[t5]" Alias="[z]" Column="a" />
              </OutputList>
              <MemoryFractions Input="1" Output="1" />
              <RunTimeInformation>
                <RunTimeCountersPerThread Thread="0" ActualRows="10000" ActualEndOfScans="1" ActualExecutions="1" />
              </RunTimeInformation>
              <Hash>
                <DefinedValues />
                <HashKeysBuild>
                  <ColumnReference Database="[planoper]" Schema="[dbo]" Table="[t5]" Alias="[z]" Column="a" />
                </HashKeysBuild>
                <HashKeysProbe>
                  <ColumnReference Database="[planoper]" Schema="[dbo]" Table="[t4]" Column="a" />
                </HashKeysProbe>
                <ProbeResidual>
                  <ScalarOperator ScalarString="[planoper].[dbo].[t4].[a]=[planoper].[dbo].[t5].[a] as [z].[a]">
                    <Compare CompareOp="EQ">
                      <ScalarOperator>
                        <Identifier>
                          <ColumnReference Database="[planoper]" Schema="[dbo]" Table="[t4]" Column="a" />
                        </Identifier>
                      </ScalarOperator>
                      <ScalarOperator>
                        <Identifier>
                          <ColumnReference Database="[planoper]" Schema="[dbo]" Table="[t5]" Alias="[z]" Column="a" />
                        </Identifier>
                      </ScalarOperator>
                    </Compare>
                  </ScalarOperator>
                </ProbeResidual>
                <RelOp AvgRowSize="11" EstimateCPU="0.0110785" EstimateIO="0.0565368" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="10000" LogicalOp="Clustered Index Scan" NodeId="1" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="0.0676153" TableCardinality="10000">
                  <OutputList>
                    <ColumnReference Database="[planoper]" Schema="[dbo]" Table="[t5]" Alias="[z]" Column="a" />
                  </OutputList>
                  <RunTimeInformation>
                    <RunTimeCountersPerThread Thread="0" ActualRows="10000" ActualEndOfScans="1" ActualExecutions="1" />
                  </RunTimeInformation>
                  <IndexScan Ordered="false" ForcedIndex="true" ForceScan="false" NoExpandHint="false">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="[planoper]" Schema="[dbo]" Table="[t5]" Alias="[z]" Column="a" />
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="[planoper]" Schema="[dbo]" Table="[t5]" Index="[c1]" Alias="[z]" IndexKind="Clustered" />
                  </IndexScan>
                </RelOp>
                <RelOp AvgRowSize="11" EstimateCPU="0.011157" EstimateIO="0.100162" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="10000" LogicalOp="Table Scan" NodeId="2" Parallel="false" PhysicalOp="Table Scan" EstimatedTotalSubtreeCost="0.111319" TableCardinality="10000">
                  <OutputList>
                    <ColumnReference Database="[planoper]" Schema="[dbo]" Table="[t4]" Column="a" />
                  </OutputList>
                  <RunTimeInformation>
                    <RunTimeCountersPerThread Thread="0" ActualRows="10000" ActualEndOfScans="1" ActualExecutions="1" />
                  </RunTimeInformation>
                  <TableScan Ordered="false" ForcedIndex="false" ForceScan="false" NoExpandHint="false">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="[planoper]" Schema="[dbo]" Table="[t4]" Column="a" />
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="[planoper]" Schema="[dbo]" Table="[t4]" IndexKind="Heap" />
                  </TableScan>
                </RelOp>
              </Hash>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

このインデックスを作成するように指示されます:

USE [planoper];
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[t4] ([a]);

回答:


21

インデックススプールを自然に表示する1つの方法は、わずかに異なる構文を使用して要件を表現することです。

SELECT DISTINCT 
    z.a
FROM dbo.t5 AS z
JOIN dbo.t4 AS y ON
    y.a >= z.a AND y.a <= z.a
OPTION (LOOP JOIN, MAXDOP 1, FORCE ORDER);

これにより、次のような実行計画が作成されます。

不平等計画に参加する

等式を同等の不等式のペアとして書き換えると、インデックススプールの使用が促進されますが、スプールされた述語は正確にはあなたのものではありませんが、セマンティクスは最終的に同じです。

元の構文を使用して目的のインデックススプールを導入する簡単な方法はありません。しかし、それが不可能だと言っているわけではありません。これはデモにのみ必要であり、本番システムの近くでは使用しないため、別の方法を示します。

SELECT 
    z.a
FROM dbo.t5 AS z WITH(INDEX(0))
WHERE 
    EXISTS 
    (
        SELECT y.a 
        FROM dbo.t4 AS y
        WHERE y.a = z.a
    )
OPTION (MAXDOP 1, LOOP JOIN, QUERYTRACEON 9114);

実行計画は次のとおりです。

トレースフラグ計画

インデックススプールの述語は、次のとおりです。

Seek Keys[1]: Prefix: [dbo].[t4].a = [dbo].[t5].[a] as [z].[a]

USE PLANオプティマイザは通常これを考慮しないため、このプランをヒントで使用することはできません。

参考文献:

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.