sql >> Database >  >> Database Tools >> SSMS

Slechte kardinaliteitsschattingen van SSMS-plannen - redux

Meer dan drie jaar geleden heb ik gepost over een oplossing voor Plan Explorer met betrekking tot slechte kardinaliteitsschattingen die Showplan XML van SQL Server produceerde, in het geval van key/RID-lookups met een filterpredikaat in SQL Server 2008 en hoger. Ik dacht dat het interessant zou zijn om terug te kijken en wat meer in detail te treden over een van deze plannen en de herhalingen die we hebben doorgemaakt om ervoor te zorgen dat we de juiste statistieken weergaven, ongeacht wat Management Studio laat zien. Nogmaals, dit werk is grotendeels gedaan door Brooke Philpott (@MacroMullet) en Greg Gonzalez (@SQLsensei) en met geweldige input van Paul White (@SQL_Kiwi).

Dit is vrij gelijkaardig aan de vraag die ik in mijn eerdere post stelde, die van Paul kwam (en die wat werk zou vergen om precies te reproduceren in moderne versies van AdventureWorks, waar op zijn minst transactiedata zijn veranderd):

SELECT
    th.ProductID,
    p.Name,
    th.TransactionID,
    th.TransactionDate
FROM Production.Product AS p
JOIN Production.TransactionHistory AS th ON
    th.ProductID = p.ProductID
WHERE 
    p.ProductID IN (1, 2)
    AND th.TransactionDate BETWEEN '20070901' AND '20071231';

Het plan van Management Studio zag er correct genoeg uit:

Als je echter beter kijkt, lijkt het erop dat ShowPlan het geschatte aantal uitvoeringen van de sleutelzoekopdracht rechtstreeks naar het geschatte aantal rijen voor de laatste uitwisseling heeft geduwd:

Op het eerste gezicht lijkt het grafische plandiagram in Plan Explorer vrij veel op het plan dat SSMS produceert:

Nu, tijdens het ontwikkelen van Plan Explorer, hebben we verschillende gevallen ontdekt waarin ShowPlan de wiskunde niet helemaal correct heeft. Het meest voor de hand liggende voorbeeld zijn percentages die optellen tot meer dan 100%; we krijgen dit goed in gevallen waar SSMS belachelijk uit is (ik zie dit tegenwoordig minder vaak dan vroeger, maar het gebeurt nog steeds).

Een ander geval is waar, vanaf SQL Server 2008, SSMS begon met het plaatsen van totale geschatte rijen in plaats van rijen per uitvoering samen met lookups, maar alleen in gevallen waarin een predikaat naar de lookup wordt gepusht (zoals het geval in deze bug gerapporteerd door Paul, en deze meer recente waarneming door Joey D'Antoni). In eerdere versies van SQL Server (en met functies en spools) toonden we doorgaans het geschatte aantal rijen dat uit een zoekopdracht komt door het geschatte aantal rijen per uitvoering (meestal 1) te vermenigvuldigen met het geschatte aantal rijen volgens SSMS. Maar met deze wijziging zouden we te veel tellen, aangezien de operator die berekening nu al uitvoert. Dus in eerdere versies van Plan Explorer, tegen 2008+, zag je deze details in de tooltips, verbindingslijnen of in de verschillende rasters:

(Waar komen 1.721 vandaan? 67,5 geschatte executies x 25,4927 geschatte rijen.)

In 2012 hebben we een deel van dit probleem opgelost door deze wiskundige bewerking niet langer uit te voeren en uitsluitend te vertrouwen op de geschatte rijtellingen die uit de sleutelzoekopdracht komen. Dit was bijna correct, maar we vertrouwden nog steeds op het geschatte aantal rijen dat ShowPlan ons voor de laatste uitwisseling gaf:

We hebben dit probleem ook snel opgelost, in versie 7.2.42.0 (uitgebracht op Hallowe'en 2012), en we hebben nu het gevoel dat we informatie verstrekken die veel nauwkeuriger is dan Management Studio (hoewel we deze bug van Paul in de gaten zullen houden) :

Dit is duidelijk al lang geleden gebeurd, maar ik vond het toch interessant om te delen. We blijven verbeteringen aanbrengen aan Plan Explorer om je de meest nauwkeurige informatie te geven die mogelijk is, en ik zal nog een paar van deze nuggets delen in komende berichten.


  1. Intellisense werkt niet in SQL Server 2014

  2. Cast FOR XML naar Varchar (max)

  3. Externe verbinding met MS SQL - Fout bij gebruik van pyodbc versus succes bij gebruik van SQL Server Management Studio

  4. Een groot veld (varbinary(max)) kopiëren naar bestand / klembord