Примусовий показник котушки


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]);

2
Ви можете поглянути на цю simple-talk.com/sql/learn-sql-server / ...
Zane

Відповіді:


21

Один із способів отримати індексну котушку природним чином - це висловити вимогу, використовуючи дещо інший синтаксис:

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 підказки, оскільки оптимізатор зазвичай не вважатиме його.

Подальше читання:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.