Ich habe sieben große Tabellen, die zu jeder Zeit zwischen 100 bis 1 Million Zeilen speichern können. Ich rufe sie LargeTable1
, LargeTable2
, LargeTable3
, LargeTable4
... LargeTable7
. Diese Tabellen sind größtenteils statisch: Es gibt keine Aktualisierungen oder neue Einfügungen. Sie ändern sich nur einmal alle zwei Wochen oder einmal im Monat, wenn sie abgeschnitten werden und eine neue Gruppe von Registern eingefügt wird. Alle diese Tabellen haben drei gemeinsame Felder: Headquarter
, und File
. Headquarter
und Country
sind Zahlen im Format "000", obwohl sie in zwei dieser Tabellen aufgrund anderer Systemanforderungen als int
geparst werden.Leistungsprobleme mit UNION von großen Tabellen
Ich habe eine andere, viel kleinere Tabelle namens Headquarters
mit den Informationen von jedem Hauptsitz. Diese Tabelle enthält nur sehr wenige Einträge. Höchstens 1000.
Nun, ich brauche eine gespeicherte Prozedur zu erstellen, die alle diese Zentrale zurückgibt, die in den großen Tabellen erscheinen, sind aber entweder nicht vorhanden in der Headquarters
Tabelle oder gelöscht wurden (diese Tabelle logisch gelöscht wird: es hat eine DeletionDate
Feld zu überprüfen Dies).
Dies ist die Abfrage, die ich versucht habe:
CREATE PROCEDURE deletedHeadquarters
AS
BEGIN
DECLARE @headquartersFiles TABLE
(
hq int,
countryFile varchar(MAX)
);
SET NOCOUNT ON
INSERT INTO @headquartersFiles
SELECT headquarter, CONCAT(country, ' (', file, ')')
FROM
(
SELECT DISTINCT CONVERT(int, headquarter) as headquarter,
CONVERT(int, country) as country,
file
FROM LargeTable1
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable2
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable3
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable4
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable5
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable6
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable7
) TC
SELECT RIGHT('000' + CAST(st.headquarter AS VARCHAR(3)), 3) as headquarter,
MAX(s.deletionDate) as deletionDate,
STUFF
(
(SELECT DISTINCT ', ' + st2.countryFile
FROM @headquartersFiles st2
WHERE st2.headquarter = st.headquarter
FOR XML PATH('')),
1,
1,
''
) countryFile
FROM @headquartersFiles as st
LEFT JOIN headquarters s ON CONVERT(int, s.headquarter) = st.headquarter
WHERE s.headquarter IS NULL
OR s.deletionDate IS NOT NULL
GROUP BY st.headquarter
END
Die Leistung dieses sp ist für unsere Anwendung nicht gut genug. Es dauert zur Zeit etwa 50 Sekunden abgeschlossen, mit den folgenden Gesamt Zeilen für jede Tabelle (nur Sie über die Größen eine Idee geben):
- LargeTable1: 1.516.666 Reihen
- LargeTable2: 645.740 Reihen
- LargeTable3 : 1950121 Reihen
- LargeTable4: 779.336 Zeilen
- LargeTable5: 1.100.999 Reihen
- LargeTable6: 16499 Zeilen
- LargeTable7: 24454 Zeilen
Was kann ich tun, um die Leistung zu verbessern? Ich habe versucht, die folgenden zu tun, ohne viel Unterschied:
- von Chargen in der lokalen Tabelle einfügen, ohne diese Zentrale ich bereits eingefügt haben und dann für diejenigen, die Country Feld zu aktualisieren, die wiederholt werden
- Erstellen einer Ansicht für die UNION-Abfrage
- Erstellen von Indizes für die LargeTables für den Hauptsitz Feld
Ich habe auch über das Einfügen dieser fehlenden Zentrale in eine permanente Tabelle nach der LargeTables
Änderung nachgedacht, aber die Headquarters
Tabelle kann öfter ändern, und ich möchte nicht sein Modul ändern müssen, um diese Dinge aufgeräumt und aktualisiert zu halten. Aber wenn es die bestmögliche Alternative ist, würde ich mich dafür entscheiden.
Dank
AFAIK die Union-Klausel wird die distinct zu tun, also keine Notwendigkeit, distinct auf Select – vercelli
@vercelli enthalten Es kann mehrere Zeilen mit der gleichen Hauptquartier-Land-Datei-Kombination in der gleichen Tabelle sein. Wird die UNION sie auch beseitigen, auch wenn sie von einem Tisch kommen? – Heathcliff
@Heathcliff ja, das ist was UNION tut. UNION ALL wird nicht. – Hogan