Mam problemy ze zrozumieniem, dlaczego pozornie prosta kwerenda, która dokonuje wewnętrznego sprzężenia na dwóch tabelach, powoduje oszacowanie liczby wierszy równej 1, gdy rzeczywisty jest prawie 2 miliony. Nie widzę żadnych problemów z brakującymi indeksami, a 98% kosztu zapytania ma miejsce w przypadku poszukiwania indeksu. Nie widzę żadnych czerwonych flag I/O lub CPU podczas wykonywania zapytań, co zajmuje około 12 sekund. Dodanie statystyk nie wydaje się mieć tutaj sensu, ponieważ zapytanie po prostu łączy się z identyfikatorami ids, a obie tabele zawierają indeksy klastrowe tych identyfikatorów jako klucze podstawowe.Proste wewnętrzne Łączenie na dwóch tabelach skutkuje błędnie oszacowanymi wierszami i małą wydajnością
To zapytanie jest uproszczoną wersją większego zapytania, w którym występują te same problemy, ale sprowadziłem je do tego uproszczonego zapytania, które napotyka ten sam problem. Zakładam, że rozbieżność pomiędzy rzędami szacunkowymi i rzeczywistymi przyczynia się przynajmniej do nieoptymalnej wydajności zapytań. Co ciekawe, podstawienie LEWEGO ZAKRESU ZEWNĘTRZNEGO dla ŁĄCZENIA WEWNĘTRZNEGO prowadzi do mniej więcej tej samej wydajności, mimo że poprawione Wiersze szacunkowe są prawidłowe.
Zapytanie:
SELECT StationId, Readings.Power, Readings.TimeCovered
FROM Readings
INNER JOIN Stations ON Readings.StationId = Stations.Id
Rzeczywista XML Plan:
<?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.1" Build="10.50.1600.1" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
<BatchSequence>
<Batch>
<Statements>
<StmtSimple StatementCompId="1" StatementEstRows="1" StatementId="1" StatementOptmLevel="FULL" StatementOptmEarlyAbortReason="GoodEnoughPlanFound" StatementSubTreeCost="0.388499" StatementText="SELECT StationId,
[Readings].[Power], [Readings].[TimeCovered]
FROM [dbo].[Readings]
INNER JOIN [dbo].[Stations] ON [Readings].[StationId] = [Stations].[Id]" StatementType="SELECT" QueryHash="0x540DF2384788314E" QueryPlanHash="0x7546B31B38AC8153">
<StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="false" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
<QueryPlan DegreeOfParallelism="1" CachedPlanSize="24" CompileTime="3" CompileCPU="3" CompileMemory="224">
<RelOp AvgRowSize="17" EstimateCPU="0.00118294" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="1" LogicalOp="Inner Join" NodeId="0" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.388499">
<OutputList>
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Column="StationId" />
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Column="Power" />
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Column="TimeCovered" />
</OutputList>
<RunTimeInformation>
<RunTimeCountersPerThread Thread="0" ActualRows="1898419" ActualEndOfScans="1" ActualExecutions="1" />
</RunTimeInformation>
<NestedLoops Optimized="false">
<OuterReferences>
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Stations]" Column="Id" />
</OuterReferences>
<RelOp AvgRowSize="11" EstimateCPU="0.0004683" EstimateIO="0.00608796" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="283" LogicalOp="Clustered Index Scan" NodeId="1" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="0.00655626" TableCardinality="283">
<OutputList>
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Stations]" Column="Id" />
</OutputList>
<RunTimeInformation>
<RunTimeCountersPerThread Thread="0" ActualRows="283" ActualEndOfScans="1" ActualExecutions="1" />
</RunTimeInformation>
<IndexScan Ordered="false" ForcedIndex="false" NoExpandHint="false">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Stations]" Column="Id" />
</DefinedValue>
</DefinedValues>
<Object Database="[MyDB]" Schema="[dbo]" Table="[Stations]" Index="[PK_Stations]" IndexKind="Clustered" />
</IndexScan>
</RelOp>
<RelOp AvgRowSize="17" EstimateCPU="0.0012571" EstimateIO="0.025" EstimateRebinds="0" EstimateRewinds="282" EstimateRows="1" LogicalOp="Index Seek" NodeId="2" Parallel="false" Partitioned="true" PhysicalOp="Index Seek" EstimatedTotalSubtreeCost="0.380759" TableCardinality="4246720">
<OutputList>
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Column="StationId" />
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Column="Power" />
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Column="TimeCovered" />
</OutputList>
<RunTimeInformation>
<RunTimeCountersPerThread Thread="0" ActualRows="1898419" ActualEndOfScans="283" ActualExecutions="283" />
</RunTimeInformation>
<RunTimePartitionSummary>
<PartitionsAccessed PartitionCount="8">
<PartitionRange Start="1" End="8" />
</PartitionsAccessed>
</RunTimePartitionSummary>
<IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" NoExpandHint="false">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Column="StationId" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Column="Power" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Column="TimeCovered" />
</DefinedValue>
</DefinedValues>
<Object Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Index="[IX_Readings_StationId_SecondsSinceEpoch]" IndexKind="NonClustered" />
<SeekPredicates>
<SeekPredicateNew>
<SeekKeys>
<StartRange ScanType="GE">
<RangeColumns>
<ColumnReference Column="PtnId1000" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="(1)">
<Const ConstValue="(1)" />
</ScalarOperator>
</RangeExpressions>
</StartRange>
<EndRange ScanType="LE">
<RangeColumns>
<ColumnReference Column="PtnId1000" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="(8)">
<Const ConstValue="(8)" />
</ScalarOperator>
</RangeExpressions>
</EndRange>
</SeekKeys>
<SeekKeys>
<Prefix ScanType="EQ">
<RangeColumns>
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Readings]" Column="StationId" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="[MyDB].[dbo].[Stations].[Id]">
<Identifier>
<ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Stations]" Column="Id" />
</Identifier>
</ScalarOperator>
</RangeExpressions>
</Prefix>
</SeekKeys>
</SeekPredicateNew>
</SeekPredicates>
</IndexScan>
</RelOp>
</NestedLoops>
</RelOp>
</QueryPlan>
</StmtSimple>
</Statements>
</Batch>
</BatchSequence>
</ShowPlanXML>
Nieaktualne statystyki mogą mieć z tym coś wspólnego. Spróbuj uruchomić 'exec sp_updatestats' i sprawdź, czy plan się zmienia. – Magnus
Magnus, wydaje się, że pomogło! Zapytanie zgłasza teraz około 4k, które pomnożone przez 283 to w przybliżeniu całkowita liczba wierszy. Pozwól mi sprawdzić, czy oryginalne zapytanie zostało przez to naprawione. – DavidN
Magnus, zadziałało to cudownie. Jeszcze raz dziękuję za twoją pomoc. – DavidN