Frage

Ich habe eine einfache indizierte Sicht. Wenn ich dagegen fragen, es ist ziemlich langsam. Zuerst zeige ich Ihnen die Indizes und Schema. Dann wird die einfachen Abfragen. Endlich ein Abfrage-Plan screnie.

Update:. Der Nachweis der Lösung am Ende dieses Beitrags

Schema

Dies ist, wie es aussieht: -

CREATE view [dbo].[PostsCleanSubjectView] with SCHEMABINDING AS
    SELECT PostId, PostTypeId, 
        [dbo].[ToUriCleanText]([Subject]) AS CleanedSubject
    FROM [dbo].[Posts]

Mein UDF ToUriCleanText ersetzt nur verschiedene Zeichen mit einem leeren Zeichen. Z.B. ersetzt alle '#' verkohlt mit ''.

Dann habe ich noch zwei Indizes auf diese: -

Indizes

Primary Key Index (dh. Clustered Index)

CREATE UNIQUE CLUSTERED INDEX [PK_PostCleanSubjectView] ON 
    [dbo].[PostsCleanSubjectView] 
(
    [PostId] 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]
GO

Und ein Non-Clustered Index

CREATE NONCLUSTERED INDEX [IX_PostCleanSubjectView_PostTypeId_Subject] ON 
    [dbo].[PostsCleanSubjectView] 
(
    [CleanedSubject] ASC,
    [PostTypeId] 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]
GO

Nun hat diese um 25K Reihen. Nichts groß überhaupt.

Wenn ich die folgenden Abfragen zu tun, sie beide nehmen rund 4 ungeradee Sekunden. WTF? Dies sollte sein .. im Grunde sofort!

Abfrage 1

SELECT a.PostId
FROM PostsCleanSubjectView a 
WHERE a.CleanedSubject = 'Just-out-of-town'

Abfrage 2 (hinzugefügt eine andere Klausel where Artikel)

SELECT a.PostId
FROM PostsCleanSubjectView a 
WHERE a.CleanedSubject = 'Just-out-of-town' AND a.PostTypeId = 1

Was habe ich falsch gemacht? Ist das UDF Einschrauben Dinge? Ich dachte, dass, weil ich diese Ansicht index'd haben, wäre es materialisiert werden. Als solches wäre es nicht, dass die String-Spalte berechnen müssen.

Hier ist ein screenie des Abfrage-Plans, wenn dies hilft: - alt text

Beachten Sie auch, den Index ist es mit? Warum ist es diesen Index mit?

Dieser Index ist ...

CREATE NONCLUSTERED INDEX [IX_Posts_PostTypeId_Subject] ON [dbo].[Posts] 
(
    [PostTypeId] ASC,
    [Subject] 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]
GO

Also ja, irgendwelche Ideen Leute?

Update. 1: Hinzugefügt Schema für die UDF

CREATE FUNCTION [dbo].[ToUriCleanText]
(
    @Subject NVARCHAR(300)
)
RETURNS NVARCHAR(350) WITH SCHEMABINDING
AS 
BEGIN
   <snip>
   // Nothing insteresting in here. 
   //Just lots of SET @foo = REPLACE(@foo, '$', ''), etc.
END

Update 2: Lösung

Ja, war es, weil ich nicht den Index für die Sicht mit und musste manuell sicherstellen, dass ich die Ansicht nicht erweitern. Der Server ist SQL Server 2008 Standard Edition. Die vollständige Antwort ist unten. Hier ist der Beweis, WITH (NOEXPAND) alt text

Vielen Dank für die Hilfe dieses Problem lösen:)

War es hilfreich?

Lösung

Welche Edition von SQL Server? Ich glaube, dass nur Unternehmen und Developer Edition indizierte Sichten automatisch verwendet werden, während die anderen unterstützen sie Abfragehinweise verwendet wird.

SELECT a.PostId
FROM PostsCleanSubjectView a WITH (NOEXPAND)
WHERE a.CleanedSubject = 'Just-out-of-town' AND a.PostTypeId = 1

Abfragehinweise (Transact SQL) auf MSDN :

  

Die indizierte Sicht nicht erweitert nur dann, wenn der Blick direkt in dem SELECT-Teil der Abfrage und MIT (NOEXPAND) oder (NOEXPAND, INDEX (index_value [, ... n])) verwiesen wird, angegeben ist.

Andere Tipps

Ich sehe ein @ -Zeichen in dem Abfrage-Code in Ihrem Ausführungsplan. Es gibt eine String-Variable beteiligt.

SQL Server hat einen fiesen Verhalten, wenn der Typ des String-Variable in dem Index nicht den Typ der String-Spalte entspricht. SQL Server ... konvertieren die gesamte Spalte auf diese Art, führen Sie das schnelle Nachschlagen und dann den konvertierte Index wegzuzuwerfen, damit es die ganze Sache wieder im nächsten Abfrage tun kann.


Simon es heraus - aber hier ist hilfreicher Detail: http: // msdn.microsoft.com/en-us/library/ms187373.aspx

  

Wenn eine Abfrage Verweise auf Spalten enthält, die vorhanden sind beide in einer indizierten Sicht und Basistabellen und der Abfrageoptimierer feststellt, dass die indizierte Sicht mit der besten Methode für die Abfrage ausgeführt wird, verwendet der Abfrageoptimierer den Index für die Sicht . Diese Funktion wird aufgerufen indizierte Sicht Anpassung , und wird nur in der SQL Server Enterprise und Developer Edition unterstützt.

     

Doch für das Optimierungsprogramm indizieren Sichten für die Anpassung zu prüfen oder eine indizierte Sicht verwenden, die mit dem NOEXPAND Hinweis, die folgenden SET-Optionen verwiesen wird, muss auf ON gesetzt werden:

So, hier passiert was ist das indizierte Sicht Anpassung funktioniert nicht. Stellen Sie sicher, Enterprise oder Developer Edition von SQL Server verwenden (ziemlich wahrscheinlich). Dann überprüfen Sie die SET-Optionen nach dem Artikel.

Ich baute vor kurzem eine große Datenbank Hunderte von Millionen von Call Detail Records enthält, und es gibt einige Funktionen, die ich in Abfragen und Ansichten verwenden, die ich in beharrten berechnete Spalten gedreht. Das funktionierte viel besser, weil ich kann Index für die berechnete Spalte.

Ich war mit SQL Enterprise nicht obwohl, so dass ich nicht die Gelegenheit bekommen indizierte Sichten zu verwenden. Ist die indizierte Sicht der deterministischen Ergebnisse der UDF-Index in der Lage sein soll?

Ich vermute, es hat für jede Zeile, um diese Funktion aufrufen, bevor sie den Vergleich in der Where-Klausel tun. Ich würde Thema aussetzen, führen Sie die Abfrage, dass die Überprüfung direkt und sehen, wie die Zeiten trainieren. Ich habe im Allgemeinen viel Langsamkeit gesehen, wenn ich einen Wert ändern, um eine Funktion und dann verwenden, in der where-Klausel ...

Welchen Nutzen suchen Sie durch eine indizierte Sicht verwenden? Ist es nicht möglich, richtig Index die Tabelle (n) selbst? Ohne eine gute Rechtfertigung, sind das Hinzufügen Sie Komplexität und fragen die Optimierer mit mehr Datenbankobjekten mit weniger Flexibilität zu behandeln.

Haben Sie die gleiche Abfragelogik mit Standard-Indizes ausgewertet?

in UDF Logik Mixing muddies Dinge noch mehr.

Wenn alles, was Sie wollen, ist der Rückgabewert einer UDF beharren, sollten Sie eine persistente berechnete Spalte, anstatt eine indizierte Sicht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top