Ich habe eine große Abfrage, die ich einstellen möchte. Ich schreibe viele Abfragen, habe aber nicht viel abgestimmt. Ich habe einen Screenshot von SQL Sentry Plan Explorer Free (SSPEF) beigefügt:
Im obigen Teil des Plans enthält die Tabelle pb_WorkRquestLog 229.001 Zeilen. Der Abfrageplan zeigt jedoch ca. 348 Millionen Zeilen (229.001 x 1.520 Iterationen):
Da es keine where-Klausel gibt, verwendet die Abfrage einen Clustered Index Scan. Ich habe alle Indizes mit FULLSCAN neu erstellt und alle Statistiken aktualisiert.
Der Code, den dieser Teil des Plans ausführt, lautet:
select distinct
wrs.ServiceKey
, owner.DepartmentName AS GroupName
, owner.UserName AS UserId
, owner.WRLCreateDateTime
, owner.WRLNotes
, wrx.CreatedDate as WRCreateDateTime
, wrx.Id
, wrx.Description
, cast(wrx.Notes as varchar(2500)) as Notes
from
prism72ext.dbo.pb_WorkRequestService wrs
Join prism72ext.dbo.pb_WorkRequest wrx on (wrs.WorkRequestId = wrx.Id and wrx.Status = 'Incomplete')
left join (
select
wl.WorkRequestId
, d.Name AS DepartmentName
, u.UserName
, wl.CreatedDate as WRLCreateDateTime
, cast(wl.Notes as varchar(2500)) as WRLNotes
from
(
SELECT
MAX( Id ) AS Id
FROM
prism72ext.dbo.pb_WorkRequestLog WITH(INDEX(0))
GROUP BY
WorkRequestId
) mwl
join prism72ext.dbo.pb_WorkRequestLog wl on mwl.Id = wl.Id
join prism72Ext.dbo.pb_Department d ON wl.DepartmentId = d.DepartmentId
left join prism72Ext.dbo.pb_User u on wl.UserId = u.UserId
) owner on wrs.WorkRequestId = owner.WorkRequestId
SSPEF meldet, dass die tatsächliche Datengröße bei 5 Millionen logischen Lesevorgängen fast 5 GB beträgt! SSMS meldet, dass die Tabelle nur 16 MB groß ist.
Ich habe die Abfrage von 4m28s auf 1m35s reduziert, aber jetzt stecke ich fest. Ich wäre dankbar, wenn mich jemand in die richtige Richtung weisen könnte, um damit umzugehen.
Bearbeiten: Jemand schlug vor, "OPTION (HASH JOIN, MERGE JOIN)" zu versuchen. Dies machte einen dramatischen Unterschied. Die E / A wurde massiv reduziert und die Abfrage wurde in 13 Sekunden ausgeführt.
Hat jemand Probleme mit dieser Lösung?
Antworten:
Wenn Sie noch keinen haben, erstellen Sie einen zusammengesetzten Index
prism72ext.dbo.pb_WorkRequestLog(WorkRequestId, Id DESC)
ohne Cluster und führen Sie die Abfrage ohne den Indexhinweis aus .Lassen Sie stattdessen Ihre innere Auswahl für die
owner
abgeleitete Tabelle zurückgeben .mwl.WorkRequestId
ml.WorkRequestId
quelle
ID
) Rekordpb_WorkRequestLog
für einen bestimmten suchenWorkRequestId
. Kann bei Vorhandensein dieses Index über einer Fensterfunktion (ROW_NUMBER() OVER (PARTITION BY pb_WorkRequestLog ORDER BY ID DESC
) eine bessere Leistung erzielt werden.Die Verwendung des Hinweises INDEX (0) erzwingt den Clustered-Index-Scan. Wenn Sie dies vermeiden möchten, müssen Sie den Hinweis entfernen. TABELLENHINWEISE :
Sie können auch versuchen, einen nicht gruppierten Index für WorkRequestId zu erstellen und die Spalten CreatedDate und Notes mithilfe der INCLUDE-Klausel einzuschließen. Beachten Sie jedoch, dass dies negative Auswirkungen auf die Einfügeleistung und die Größe der Tabelle haben kann.
Wenn Sie den Datenbanknamen in Abfragen fest codieren, ist es äußerst schwierig, den Code in Testumgebungen zu verschieben, es sei denn, Sie können sich eine einzelne Datenbank pro Serverinstanz leisten.
quelle