Frage

Ich habe eine Tabelle mit 5.651.744 Zeilen bekommt, mit einem Primärschlüssel aus 6 Spalten (int x 3, smallint, varchar (39), varchar (2)). Ich suche die Leistung mit dieser Tabelle und eine andere Tabelle, die teilt diese Primärschlüssel sowie eine zusätzliche Spalte hinzugefügt, aber 37m Reihen hat zu verbessern.

In Erwartung einer Spalte des Hinzufügens des Hash-Schlüssel zu erstellen, ich eine Analyse tat und fand 18.733 Kollisionen.

SELECT  SUM(CT)
FROM    (
         SELECT HASH_KEY
               ,COUNT(*) AS CT
         FROM   (
                 SELECT CHECKSUM(DATA_DT_ID, BANK_NUM, COST_CTR_NUM,
                                 GL_ACCT_NUM, ACCT_NUM, APPN_CD) AS HASH_KEY
                 FROM   CUST_ACCT_PRFTBLT
                ) AS X
         GROUP BY HASH_KEY
         HAVING COUNT(*) > 1
        ) AS Y

SELECT  COUNT(*)
FROM    CUST_ACCT_PRFTBLT

Es ist etwa doppelt so schlecht mit BINARY_CHECKSUM()

Sind diese zu hoch erscheinen (0,33%) die kleinere relative Menge des Zielraumes gegeben Ich bin bedeckt? Und wenn die Kollisionen dieses hoch sind, ist es ein Vorteil auf diesem hergestellten Schlüssel zuerst in Verbindung in den Kosten für das zusätzlichen 4 Bytes pro Zeile verbindet, da Sie immer noch auf den regulären Spalten zu verbinden haben die gelegentliche Kollision zu behandeln?

War es hilfreich?

Lösung

Ich sehe nicht, wo eine Prüfsumme hinzugefügt werden Sie etwas mit diesem Niveau von Kollisionen bekommen. Auch 1 Kollision zu viele, wie es Ihnen auf die falschen Daten verbinden verursachen würde. Wenn Sie nicht auf den richtigen Datensatz beitreten können gewährleisten, ist es sinnlos, wenn es die Leistung verbessert, aber verwirrt mit der Datenintegrität. Dies scheint Finanzdaten zu sein, also sollten Sie wirklich sicher sein, dass Ihre Anfragen nicht schlecht Ergebnisse angezeigt werden können. Man könnte tatsächlich am Ende Abbuchung oder die falschen Konten gutgeschrieben, wenn es irgendwelche Kollisionen.

Wenn Sie diesen Weg gehen, Marc ist richtig, dass Sie sollen, wenn möglich vorab berechnen (Hinzufügen eine Berechnung, die zu jedem Datensatz in Multisatztabellen geschehen hat nicht wahrscheinlich ist, die Leistung in meiner Erfahrung zu verbessern). Möglicherweise, wenn Sie die vorberechneten Spalte tun können (und Sie Trigger müssen es immer up-date), dann müssen Sie möglicherweise nicht auf allen sechs der anderen Spalten verbinden keine Kollisionen zu gewährleisten. Dann vielleicht könnten Sie imporved Leistung haben. Alles, was Sie tun können, ist Ihre Theorie zu testen. Aber sehr sicher, dass Sie haben keine Kollisionen.

Haben Sie einen Ersatzschlüssel betrachtet und anschließend einen eindeutigen Index für die sechs natürlichen Schlüsselfelder statt? Dann könnte man auf dem Ersatzschlüssel verbinden und wahrscheinlich würde, dass die Leistung ein gutes Stück verbessern. Es kann nicht effizient sein, auf sechs Säulen zu verbinden (eine varchar) anstelle eines Ersatzschlüssel. Mir ist klar, von der Größe der Daten, könnte dies schwieriger sein, als Refactoring in einem Nicht-Produktionssystem, aber wirklich kann es die Ausfallzeit wert sein, um permananently persistent Performance-Probleme zu beheben. Nur kann man sagen, wie komplex eine Änderung dieses und wie schwer wäre es, alle sps oder Fragen zu einem besseren beitreten zu ändern wäre. Allerdings könnte es möglich sein, zu versuchen.

Andere Tipps

Was ich habe viele Leute gesehen, so weit zu beschönigen ist, dass CHECKSUM eine Tonne von Kollisionen hat, von Microsoft selbst zugibt . Es ist sogar noch schlimmer als MD5, die ihren fairen Anteil an sinnvollen Kollisionen haben.

Wenn Sie suchen eine Hash-Spalte zu erhalten, sollten Sie mit HASHBYTES mit SHA1 angegeben.  SHA1 hat viel weniger aussagekräftig Kollisionen als MD5 oder CHECKSUM. Daher CHECKSUM sollte nie zu bestimmen, verwendet werden, wenn eine Reihe einzigartig ist, sondern es ist eine schnelle Überprüfung der Genauigkeit von zwei Werten. Daher sollten Sie Ihre Kollisionsrate 0% mit HASHBYTES sein, es sei denn, Sie doppelte Zeilen haben (die PK ist, sollte nie passieren).

Beachten Sie, dass HASHBYTES wird etwas größer als 8000 Bytes abgeschnitten, aber Ihre PK ist viel weniger als die (alle verketteten), so dass Sie keine Probleme haben sollte.

Wenn Ihre Prüfsumme es wird auf 0,33% der Daten nach unten, dann würde ich argumentieren, dass es funktioniert gut ... vor allem, wenn Sie diese Spalte in Kombination verwenden, um mit anderen (indexierten) Spalten.

Natürlich wirksam zu sein als Index mögen Sie wahrscheinlich diesen Wert berechnen und zu speichern, wenn das Einfügen / Aktualisieren von Daten mit einem nicht gruppierten Index.

Natürlich regelmäßig Spanning Index über die Spalten in Frage kann genauso gut oder besser ...

Wenn Ihre Abfragen selektiv und die Linientabelle gruppierten Index ist schmal oder nicht vorhanden sind, dann wird ein nicht gruppierten Index auf Prüfsumme in der Leitungstabelle sollte eine gute Leistung.

Nach der Anwendung, was Kriterien vorhanden ist, an die Kopftabelle, wird die Prüfsumme verwendet ein Index sucht auf dem nicht gruppierten Index durchzuführen. Sie müssen noch die FKs in der Verbindung schließen, aber das Nicht-Prüfsumme Verknüpfungskriterien post-Index suchen, post-Lesezeichen-Suche angewandt werden. Sehr effizient.

Sie wollen versuchen, für den Index zu optimieren. Die Prüfsumme ist schon sehr selektiv. Das Hinzufügen der FKs erhöhen würde die Indexgröße und entsprechendes I / O, und würde nicht helfen, wenn es genug anderen Felder enthält insgesamt die Lesezeichen-Suche zu vermeiden.

Da die nicht gruppierten Index die Clustering-Schlüssel oder Heapzeiger enthalten wird, Sie wollen entweder a) ein kleines Clustering-Schlüssel (zB ein int Identitätsspalte - 4-Byte-Zeiger) oder b) kein Clustered-Index überhaupt (8 Byte-Zeiger).

Wenn Ihre Abfragen sind nicht selektiv, oder wenn die Linientabelle gruppierten Index ist riesig (die gesamte Tabelle minus ein paar Spalten), dann weiß ich nicht, ob die Prüfsumme helfen würde (schneller Index Navigation, vielleicht?). Auf jeden Fall würden Sie es einen gruppierten oder abdeckenden Index zu machen, und wenn der Header-Tabelle auf der Prüfsumme zunächst nicht gruppiert ist, wird es viel Sortierung sein.

Wenn Sie die Speicherung und Indizierung Kosten leisten können, ein paar Deck indexes - Header und Detail -. Kann der Weg zu gehen

Wenn Ihr PRIMARY KEY gruppiert ist, dann wird jeder Index Sie erstellen, wird diesen PRIMARY KEY enthält.

auf einem Hash-Wert Beitritt wird diese folgenden Schritte aus:

  1. Suchen Sie den Hash-Wert im Indexschlüssel
    • Suchen Sie den PRIMARY KEY Wert in den Indexdaten
    • Verwenden Sie Clustered Index Seek die PRIMARY KEY Zeile in der Tabelle
    • lokalisieren

auf einem PRIMARY KEY Joining nur den Schritt 3 verwenden.

SQL Server ist aber klug genug, dies zu berücksichtigen, und wenn Sie so beitritt:

SELECT  *
FROM    main_table mt
JOIN    CUST_ACCT_PRFTBLT cap
ON      cap.HASH_KEY = mt.HASH_KEY
        AND cap.DATA_DT_ID = mt.DATA_DT_ID
        AND …
WHERE   mt.some_col = @filter_value

, es wird nicht nur den Index auf HASH_KEY verwenden, stattdessen wird es eine einzige Clustered Index Seek und Filter verwenden, um sicher die Hash-Werte übereinstimmen zu machen (und sie werden immer).

Zusammenfassung : Werden Sie Mitglied nur auf dem PRIMARY KEY

.

einen Sekundärindex verwenden, müssen Sie zuerst eine nutzlose HASH_KEY Suche tun müssen, und dann müssen noch auf dem PRIMARY KEY verbinden.

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