2015-01-27 4 views
7

Ich habe die folgende Abfrage, die < 1s nimmt, wenn ORDER BY b.Price verwendet wird, und 10s über, wenn ORDER BY b.Price DESC verwendet wirdORDER BY indexierte Spalte ist immer noch langsam

select * from 
(
    select 
     /* When changed to ORDER BY b.Price DESC it's 10x slower! */ 
     (row_number() over (ORDER BY b.Price)) as RowNumber, 
     b.*  
    from 
     Books b (nolock) 
     inner join BookPublishRegions p (nolock) 
      on b.BookKey = bp.BookKey 
    where  
     contains(p.PublishRegionName, 'France') 
) as t1 
where t1.RowNumber between 100 and 110 

Irgendwelche Gedanken auf, warum?

Ich habe sowohl einen aufsteigenden und absteigenden Index auf b.Price. Ich bin nicht wirklich sicher, was sonst kann ich hier tun ...

Als Referenz ich bin auch das Skript für beiden Indizes CREATE unten:

CREATE NONCLUSTERED INDEX [IX_Books_PriceDesc] ON [dbo].[Books] 
(
    [Price] DESC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 


CREATE NONCLUSTERED INDEX [IX_Books_Price] ON [dbo].[Books] 
(
    [Price] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
+0

Zeigen Sie uns die Indizes –

+0

Sie wahrscheinlich den Index auf Preis asc Änderung es DESC https://technet.microsoft.com/en-us/library/ms181154%28v=sql.105%29.aspx – Mihai

+0

Vielleicht haben Sie könnte uns eine EXPLAIN zeigen? –

Antwort

0

ich bei dem geschätzten Abfrage-Plan aussehen würde in SSMS (Strg + L). Mein Verdacht ist, dass es keinen der Indizes verwendet, da sie nicht abdecken.

Außerdem führt es im Fall der langsameren absteigenden Option eine andere Sortieroption ein, da die Daten wahrscheinlich bereits in der ausgewählten Join-Strategie einsortiert werden.

Ohne an dem aktuellen Abfrage-Plan zu suchen, ist dies alles nur um wilde Spekulationen

+0

Haben Sie erwogen, keine Platzhalter (*) in Ihren Selects zu verwenden? – KonB

0

Sie haben versucht, nur den aufsteigenden Index mit der absteigenden Reihenfolge verwenden? Laut diesem Artikel sollte es genauso schnell sein, um den aufsteigenden Index und die aufsteigende Reihenfolge zu haben, und eliminiert den Bedarf für den absteigenden Index. Einen Versuch wert seit einem schnellen Experiment. Building SQL Server Indexes in Ascending vs Descending Order

0

Ich würde versuchen, die Indizes hart in die Select-Anweisung zu codieren. Da haben Sie den Index vordefiniert.

Die Syntax ist

With (NOLOCK, Index(Index_Name)) 
2

Als ein anderer Benutzer erwähnt hat, es wilde Spekulation ist ein Abfrage-Plan, ohne zu sehen. Aber ich wäre überrascht, wenn die Abfrage in beiden Fällen einen Index verwendet hätte. Auch wenn sie Indizes abdecken, filtern Sie das Ergebnis einer Fensterfunktion in einer Unterabfrage. Der Planer kann nicht wissen, für welche Zeilen die Funktion Zeilennummer 100-110 zurückgibt, bis sie das gesamte Ergebnis in der Datei analysiert hat Unterabfrage, und Sie haben die Unterabfrage tatsächlich auch nicht nach Preis sortiert, so dass es keinen Nutzen darin hätte, einen der Indizes zu verwenden. Ich kann nicht erklären, warum es im aufsteigenden Fall unter diesen Bedingungen schneller ist, aber wir müssten einen Abfrageplan sehen, um das herauszufinden, aber ich vermute, dass etwas anderes im Spiel sein könnte.

Es sieht aus, als ob Sie die Fensterfunktion tun Paging zu implementieren, wenn ja, und Sie sind mit 2012 oder höher, versuchen Sie/Offset- holen statt, zB:

select 
    b.*  
from 
    Books b (nolock) 
    inner join BookPublishRegions p (nolock) 
     on b.BookKey = bp.BookKey 
where  
    contains(p.PublishRegionName, 'France') 
order by price desc 
offset 100 fetch 10 

Der Planer kann es erkennen, kann dann den Index verwenden. Obwohl es wahrscheinlich ein geclusterter oder deckender Index sein müsste, um ehrlich zu sein, einen Unterschied zu machen.

Wenn Sie 2008 oder früher arbeiten, versuchen Sie, eine explizite Reihenfolge zu erstellen und die Unterabfrage zu übernehmen, damit der Planer erkennt, dass er den Index verwenden kann. Sie können weiterhin die Fensterfunktion und Filter in einer äußeren Abfrage verwenden, um das Paging zu tun, aber auf diese Weise wird es hoffentlich die Fensterfunktion über weit weniger Zeilen laufen:

select * from 
(
select top 110 
    (row_number() over (ORDER BY b.Price DESC)) as RowNumber, 
    b.*  
from 
    Books b (nolock) 
    inner join BookPublishRegions p (nolock) 
     on b.BookKey = bp.BookKey 
where  
    contains(p.PublishRegionName, 'France') 
ORDER BY b.Price DESC 
) as t1 
where t1.RowNumber between 100 and 110 
0

Bitte rufen Sie einen Abfrage-Plan, indem einfach „erklären "vor Ihrer SELECT-SQL-Abfrage. Es beantwortet die Frage, ob überhaupt Indizes zur Auswertung der Abfrage verwendet werden.

0

Sind beide Szenarien die von Ihnen erwähnten Indizes? Oder verwendet das ASC-Beispiel einen anderen Index, der keine Schlüsselsuche für die Auswahl ". *" benötigt.

Verwandte Themen