Frage

erbte ich ein neues System und ich versuche, einige Verbesserungen auf den Daten zu machen. Ich versuche, diese Tabelle zu verbessern und kann nicht scheinen Sinn meiner Entdeckungen zu machen.

Ich habe die folgende Tabellenstruktur:

CREATE TABLE [dbo].[Calls](
    [CallID] [varchar](8) NOT NULL PRIMARY KEY,
    [RecvdDate] [varchar](10) NOT NULL,
    [yr] [int] NOT NULL,
    [Mnth] [int] NOT NULL,
    [CallStatus] [varchar](50) NOT NULL,
    [Category] [varchar](100) NOT NULL,
    [QCall] [varchar](15) NOT NULL,
    [KOUNT] [int] NOT NULL)

Diese Tabelle hat über 220k Datensätze drin. Ich brauche alle Datensätze zurück, die ein Datum größer als festes Datum hat. In diesem Fall 2009.12.01. Diese Abfrage wird über 66k Datensätze zurück, und es dauert ungefähr 4 Sekunden zu laufen. Aus früheren Systemen habe ich gearbeitet scheint hoch. Zumal, wie wenige Datensätze in der Tabelle sind. So möchte ich, dass die Zeit nach unten bringen.

Also ich frage mich, was einige gute Möglichkeiten wäre, dass nach unten zu bringen? Ich habe versucht, ein Datum Spalte der Tabelle hinzugefügt und die Zeichenfolge Datum zu einer tatsächlichen Datumsspalte zu konvertieren. Dann habe ich einen Index zu diesem Zeitpunkt Spalte, aber die Zeit gleich geblieben. Da gibt es nicht so viele Platten, die ich sehen kann, wie ein Tabelle-Scan schnell sein könnte, aber ich würde denken, dass ein Index, dass die Zeit nach unten bringen könnte.

Ich habe erwogen Abfrage auch nur den Monat und das Jahr Spalten ab. Aber ich habe es noch nicht probiert. Und möchte es an der Datumsspalte halten, wenn möglich. Aber wenn nicht ich kann es ändern.

Jede Hilfe sehr geschätzt wird.

EDIT: Hier ist die Abfrage Ich versuche, um die Geschwindigkeit der Tabelle auszuführen und zu testen. Ich in der Regel die Spalten löschte aber nur der Einfachheit halber habe ich *:

SELECT *
FROM _FirstSlaLevel_Tickets_New
WHERE TicketRecvdDateTime >= '12/01/2009'

EDIT 2: Also ich erwähnt, dass ich versucht hatte, eine Tabelle mit einer Datumsspalte zu erstellen, die die recvddate Daten enthalten, sondern als ein Datum statt einer varchar. Das ist, was TicketRecvdDateTime Spalte in der Abfrage oben. Die ursprüngliche Abfrage, die ich für diese Tabelle leite ist:

SELECT *
FROM Calls
WHERE CAST(RecvdDate AS DATE) >= '12/01/2009'
War es hilfreich?

Lösung

Sie können sie zu treffen, was als Tipping Point in SQL Server bezeichnet wird. Auch wenn Sie den entsprechenden Index für die Spalte haben, können SQL Server entschieden, ein Tabellen-Scan sowieso zu tun, wenn die erwartete Anzahl der zurückgegebenen Zeilen eine gewisse Schwelle überschreitet (der ‚Tipping Point‘).

In Ihrem Beispiel scheint dies wahrscheinlich, da Ihr dreht 1/4 der Anzahl der Zeilen in der Datenbank. Im Folgenden ist ein guter Artikel, der diese erklärt: http://www.sqlskills.com/BLOGS/KIMBERLY/category/The-Tipping-Point.aspx

Andere Tipps

SELECT * wird in der Regel einer schlechte Leistung.

Entweder der Index wird ignoriert, oder Sie werden mit einem Schlüssel / Lesezeichen-Suche in den Clustered-Index am Ende. Egal. Beide können schlecht laufen

Zum Beispiel, wenn Sie diese Abfrage haben, und den Index auf TicketRecvdDateTime inbegriffen callstatus, dann wäre es höchstwahrscheinlich wie erwartet ausgeführt. Dies wäre Abdeckung

SELECT CallStatus
FROM _FirstSlaLevel_Tickets_New
WHERE TicketRecvdDateTime >= '12/01/2009'

Dies zusätzlich zu Randy Minder Antwort ist: a. Schlüssel / Lesezeichen-Suche billig genug für eine Handvoll Zeilen sein kann, aber nicht für einen großen Teil der Tabellendaten

Ihre Abfrage ist schneller w / o einen Index (oder mehr precisly, ist die gleiche Geschwindigkeit w / oder w / o Index) da und Index auf RecvdDate wird immer in einem Ausdruck ignoriert werden wie CAST(RecvdDate AS DATE) >= '12/01/2009'. Dies ist ein nicht-SARG-able Ausdruck, da es die Spalte erfordert Trog eine Funktion umgewandelt werden. Um für diesen Index Ereignis betrachtet werden , müssen Sie Ihre Filterkriterien auszudrücken genau auf der Spalte indiziert werden, nicht auf einem Ausdruck auf sie basiert. Dies wäre der erste Schritt sein.

Es gibt mehrere Schritte:

  • Nehmen Sie das Datum der VARCHAR (10) Spalte befreien und ersetzen Sie es mit dem entsprechenden DATE oder DATETIME- Spalte. Speichern von Datum und / oder Zeit als Strings mit Problemen gespickt. Nicht nur für die Indizierung, sondern auch für die Richtigkeit.
  • Eine Tabelle, die häufig auf einem Bereich abgetastet wird, basierend auf einer Säule (wie die meisten solches Anrufprotokoll Tabellen sind) soll nach dieser Spalte gruppiert werden.
  • Es ist sehr unwahrscheinlich, dass Sie wirklich die yr und mnth Spalten benötigen. Wenn Sie wirklich brauchen sie das tun, dann müssen Sie sie vielleicht als berechnete Spalten.

.

CREATE TABLE [dbo].[Calls](
    [CallID] [varchar](8) NOT NULL,
    [RecvdDate] [datetime](10) NOT NULL,
    [CallStatus] [varchar](50) NOT NULL,
    [Category] [varchar](100) NOT NULL,
    [QCall] [varchar](15) NOT NULL,
    [KOUNT] [int] NOT NULL,
    CONSTRAINT [PK_Calls_CallId] PRIMARY KEY NONCLUSTERED ([CallID]));

CREATE CLUSTERED INDEX cdxCalls ON Calls(RecvDate);

SELECT *
FROM Calls
WHERE RecvDate >= '12/01/2009';

Natürlich ist die richtige Struktur der Tabelle und Indizes sollte das Ergebnis einer sorgfältigen Analyse, wenn man bedenkt alle Faktoren beteiligt, einschließlich Update Leistung, andere Abfragen etc. Ich Sie, indem Sie durch alle beginnen empfehlen die darin enthaltenen Themen in Designing Indizes .

Können Sie ändern Ihre Anfrage? Wenn einige Spalten benötigt werden, können Sie die SELECT-Klausel ändern, um weniger Spalten zurück. Und dann können Sie einen abdeckenden Index erstellen, die alle Spalten verwiesen enthält, einschließlich TicketRecvdDateTime.

Sie können den Index für TicketRecvdDateTime erstellen, aber Sie können den Kipppunkt nicht vermeiden, dass @Randy Minder diskutiert. Jedoch kann ein Scan auf dem kleineren Index (kleiner als Tabellen-Scan) würde weniger Seiten zurück.

Unter der Annahme, RecvdDate ist die TicketRecvdDateTime Sie sprechen:

SQL Server vergleicht nur Daten in einfache Anführungszeichen, wenn der Feldtyp DATE ist. Ihre Anfrage wird sie wahrscheinlich als VARCHAR zu vergleichen. versuchen Sie, eine Zeile mit '99 / 99 / 0001' und sehen, ob es an der Unterseite zeigt.

Wenn ja, sind Ihre Abfrageergebnisse nicht korrekt. Ändern Typ DATE.

Beachten Sie, dass VARCHAR nicht indizieren gut, DATETIME- der Fall ist.

Überprüfen Sie den Abfrage-Plan zu sehen, ob seine Indizes verwenden. Wenn die DB ist klein im Vergleich zu dem verfügbaren RAM, kann es einfach Tabellen-Scan und hält alles im Speicher.

EDIT: Auf dem CAST / DATETIME- bearbeiten zu sehen, lassen Sie mich darauf hinweisen, dass Sie ein Datum aus einem VARCHAR Parsen eine sehr teuere Operation ist. Sie tun dies 220k mal. Dadurch wird die Leistung töten.

Sie sind auch keine Kontrolle mehr auf einem indizierten Feld. ein Vergleich mit einem Ausdruck ein Indexfeld Einbeziehung der Index nicht verwendet werden.

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