Heim >Datenbank >MySQL-Tutorial >Eine kurze Diskussion zur Optimierung von SQL-Anweisungen

Eine kurze Diskussion zur Optimierung von SQL-Anweisungen

伊谢尔伦
伊谢尔伦Original
2016-12-03 11:07:27960Durchsuche

(1) Wählen Sie die effizienteste Reihenfolge der Tabellennamen (nur gültig im regelbasierten SEO/' target='_blank'> Optimierer):
Der Parser von ORACLE verarbeitet die Tabelle in der Reihenfolge von rechts nach links Der Name in der FROM-Klausel wird zuerst verarbeitet. Wenn die FROM-Klausel mehrere Tabellen enthält, müssen Sie die kleinste Anzahl von Datensätzen als Basistabelle auswählen. Wenn die Abfrage mehr als drei Tabellen umfasst, müssen Sie die Schnitttabelle als Basistabelle auswählen. Die Kreuztabelle bezieht sich auf die Tabelle, auf die andere Tabellen verweisen Klausel . :
ORACLE verwendet eine Bottom-up-Reihenfolge zum Parsen von WHERE-Klauseln. Nach diesem Prinzip müssen Verbindungen zwischen Tabellen vor anderen WHERE-Bedingungen geschrieben werden, die die maximale Anzahl von Datensätzen herausfiltern können . Am Ende. (3) Vermeiden Sie die Verwendung von „*“ in der SELECT-Klausel:
Während des Parsing-Prozesses wird ORACLE nacheinander „*“ in alle Spaltennamen umwandeln dictionary , was bedeutet, dass es mehr Zeit in Anspruch nehmen wird
(4) Reduzieren Sie die Anzahl der Zugriffe auf get='_blank'>database:
ORACLE führt intern viel Arbeit aus: SQL-Anweisungen analysieren, Indexauslastung schätzen, Bind Variablen, Datenblöcke lesen usw.;
(5) Setzen Sie den Parameter ARRAYSIZE in SQL*Plus, SQL*Forms und Pro*C zurück, um die Menge der abgerufenen Daten für jeden get='_blank'> der empfohlene Wert ist 200
(6) Verwenden Sie die DECODE-Funktion, um die Verarbeitungszeit zu verkürzen:
Verwenden Sie die DECODE-Funktion, um wiederholtes Scannen derselben Datensätze oder wiederholtes Verbinden derselben Tabelle zu vermeiden.
(7) Integrieren Sie einfache, unkorrelierter get='_blank'>Datenbankzugriff:
Wenn Sie mehrere einfache get='_blank'>Datenbankabfrageanweisungen haben, können Sie diese in einer Abfrage kombinieren (auch wenn keine Beziehung zwischen ihnen besteht)
(8) Doppelte Datensätze löschen:
Die effizienteste Methode zum Löschen doppelter Datensätze (da ROWID verwendet wird) Beispiel:
DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP Informationen, die wiederhergestellt werden können, wenn Sie keine COMMIT-Transaktion haben, stellt ORACLE die Daten in den Zustand vor dem Löschen wieder her (genauer gesagt in den Zustand vor der Ausführung des Löschbefehls). Das Segment speichert keine wiederherstellbaren Daten mehr. Wenn der Befehl ausgeführt wird, werden nur wenige Ressourcen aufgerufen und die Ausführungszeit ist sehr kurz Tabelle, TRUNCATE ist DDL, nicht DML)
(10) Verwenden Sie COMMIT so oft wie möglich:
Wenn möglich, verwenden Sie COMMIT so oft wie möglich im Programm, damit die Leistung des Programms verbessert und die Anforderungen erfüllt werden wird aufgrund der von COMMIT freigegebenen Ressourcen reduziert:
Durch COMMIT freigegebene Ressourcen:
Informationen, die zum Wiederherstellen von Daten im Rollback-Segment verwendet werden im Redo-Log-Puffer
d. ORACLE verwaltet die oben genannten internen Kosten zwischen 3 Ressourcen
(11) Ersetzen Sie die HAVING-Klausel durch die Where-Klausel:
Vermeiden Sie die Verwendung der HAVING-Klausel, HAVING filtert die Ergebnismenge nur danach Alle Datensätze wurden abgerufen. Wenn Sie die Anzahl der Datensätze mithilfe der WHERE-Klausel begrenzen können, können Sie den Overhead in diesem Bereich reduzieren Es gibt drei Klauseln, die Bedingungen hinzufügen können: „on“ wird zuerst ausgeführt, gefolgt von „where“ und „zuletzt“. Da „on“ zuerst die Datensätze filtert, die die Bedingungen nicht erfüllen, kann dies die in der Zwischenoperation zu verarbeitenden Daten reduzieren Logischerweise sollte es am schnellsten sein, und das gilt auch für where. Es ist schneller als have, da es die Daten vor der Durchführung der Summe filtert und nur dann verwendet wird, wenn zwei Tabellen zusammengeführt werden. Daher werden nur where und have verwendet verglichen. Wenn bei Einzeltabellen-Abfragestatistiken die zu filternden Bedingungen nicht die zu berechnenden Felder betreffen, sind ihre Ergebnisse dieselben, mit der Ausnahme, dass die Rushmore-Technologie verwendet werden kann, dies jedoch nicht möglich ist und letztere langsamer ist Das Einbeziehen eines berechneten Feldes bedeutet, dass der Wert dieses Feldes vor der Berechnung ungewiss ist In diesem Fall werden die Ergebnisse der beiden unterschiedlich sein. Bei Mehrtabellen-Join-Abfragen wird on früher wirksam als where. Das System kombiniert zunächst mehrere Tabellen zu einer temporären Tabelle basierend auf den Verbindungsbedingungen zwischen den einzelnen Tabellen, filtert dann nach „Wo“ und berechnet dann. Es ist ersichtlich, dass Sie, wenn Sie möchten, dass die Filterbedingung eine korrekte Rolle spielt, zunächst verstehen müssen, wann die Bedingung wirksam werden soll, und dann entscheiden müssen, sie dort zu platzieren
(12) Reduzieren Sie die Abfrage der Tabelle:
In der Abfrage-SQL-Anweisung sollte besonders darauf geachtet werden, die Anzahl der Tabellenabfragen zu reduzieren: = 604)
( 13) Verbessern Sie die SQL-Effizienz durch interne Funktionen:
Komplexes SQL beeinträchtigt häufig die Ausführungseffizienz. Die Beherrschung der oben genannten Methode zur Verwendung von Funktionen zur Lösung von Problemen ist in der tatsächlichen Arbeit sehr sinnvoll
(14 ) Verwenden von Tabellen Alias:
Wenn Sie mehrere Tabellen in einer SQL-Anweisung verbinden, verwenden Sie bitte den Alias ​​der Tabelle und stellen Sie den Alias ​​jeder Spalte voran. Auf diese Weise können Sie die Analysezeit reduzieren und die durch Spaltenmehrdeutigkeit verursachten Syntaxfehler reduzieren. Verwenden Sie EXISTS anstelle von IN, verwenden Sie NOT EXISTS anstelle von NOT IN:
Um eine Bedingung zu erfüllen, ist es in vielen Abfragen häufig erforderlich, eine andere Tabelle zu verknüpfen. Verwenden Sie in diesem Fall EXISTS( oder NOT EXISTS) verbessert im Allgemeinen die Effizienz der Abfrage. In beiden Fällen führt die NOT IN-Klausel eine vollständige Tabellendurchquerung durch Um die Verwendung von NOT IN zu vermeiden, können wir es in Outer Joins oder NOT EXISTS umschreiben.
Beispiel:
(Effizient) SELECT * FROM EMP (Basistabelle) WHERE EMPNO > 0 AND EXISTS (SELECT 'X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = 'MELB')
(Ineffizient) SELECT * FROM EMP (Basistabelle) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = 'MELB')
(16) Identifizieren Sie „ineffiziente Ausführung“ von SQL-Anweisungen:
Obwohl es derzeit verschiedene Optimierungen für SQLseo/' target='_blank'> gibt, gibt es unzählige grafische Tools, aber das Schreiben eigener SQL-Tools ist immer das Beste So lösen Sie Probleme:
SELECT EXECUTIONS, DISK_READS, BUFFER_GETS,
ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio ,
ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,
SQL_TEXT
FROM V$SQLAREA
WHERE EXECUTIONS>0
AND BUFFER_GETS > 0
AND (BUFFER_GETS-DISK_READS)/ BUFFER_GETS < 0.8
ORDER BY 4 DESC;
(17) Verwenden Indizes zur Verbesserung der Effizienz:
Der Index ist ein konzeptioneller Teil der Tabelle, der zur Verbesserung der Effizienz beim Abrufen von Daten verwendet wird. ORACLE verwendet eine komplexe selbstausgleichende B-Baum-Struktur. Im Allgemeinen ist die Abfrage von Daten über Indizes schneller als eine vollständige Wenn ORACLE den besten Pfad zum Ausführen von Abfragen und Update-Anweisungen ermittelt, verwendet der ORACLEseo/'_blank'>-Indizes auch die Effizienz beim Zusammenführen mehrerer Tabellen besteht darin, dass es eine Eindeutigkeitsüberprüfung des Primärschlüssels ermöglicht. Mit diesen LONG- oder LONG RAW-Datentypen können Sie fast jede Spalte indizieren. Im Allgemeinen ist die Verwendung von Indizes besonders effektiv bei großen Tabellen. Natürlich können Sie auch die Effizienz beim Scannen kleiner Tabellen verbessern Die Effizienz kann verbessert werden, aber wir müssen auch auf die Kosten achten. Immer wenn Datensätze in der Tabelle hinzugefügt oder gelöscht werden, wird auch der Index selbst geändert dass INSERT, DELETE und UPDATE für jeden Datensatz 4 oder 5 weitere Festplatten-I/Os kosten, da Indizes zusätzlichen Speicherplatz und Verarbeitung erfordern, verkürzen diese unnötigen Indizes tatsächlich die Antwortzeit. Eine regelmäßige Neuerstellung der Indizes ist erforderlich.:
ALTER INDEX REBUILD
18) Ersetzen Sie DISTINCT durch EXISTS:
Wenn Sie eine Abfrage senden, die Eins-zu-Viele-Tabelleninformationen enthält (z. B. Abteilungstabellen und Mitarbeitertabellen), Vermeiden Sie die Verwendung von DISTINCT in der SELECT-Klausel. Im Allgemeinen können Sie erwägen, die Abfrage durch EXISTS zu ersetzen, da das RDBMS-Kernmodul die Ergebnisse sofort zurückgibt, sobald die Bedingungen der Unterabfrage erfüllt sind ):
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D, EMP E
WHERE D.DEPT_NO = E.DEPT_NO
(effizient):
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT 'X '
FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
(19) server/' target='_blank'> Die SQL-Anweisung ist in Großbuchstaben geschrieben, da Oracle immer zuerst server/' target= analysiert '_blank'>SQL-Anweisung, Kleinbuchstaben in Großbuchstaben umwandeln und dann ausführen
(20) Verwenden Sie den Connector „+“ so wenig wie möglich, um Zeichenfolgen im Java-Code zu verbinden!
(21) Vermeiden Sie die Verwendung von NOT für Indexspalten. Generell gilt:
Wir möchten vermeiden, dass die Verwendung von NOT für Indexspalten die gleichen Auswirkungen hat wie die Verwendung von Funktionen für Indexspalten Verwenden Sie den Index und führen Sie einen vollständigen Tabellenscan durch. (22) Vermeiden Sie die Verwendung von Berechnungen für Indexspalten.
In der WHERE-Klausel, wenn die Indexspalte Teil der Funktion ist. seo/' target='_blank'>Der Optimierer verwendet keine Indizes, sondern vollständige Tabellenscans.
Beispiel:
Ineffizient:
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
Effizient:
SELECT … FROM DEPT WHERE SAL > 25000/12;
( 23 ) Verwenden Sie >= anstelle von>
Effizient:
SELECT * FROM EMP WHERE DEPTNO >=4
Ineffizient:
SELECT * FROM EMP WHERE DEPTNO >3
Beide Der Unterschied ist dass das erstere DBMS direkt zum ersten Datensatz mit DEPT gleich 4 springt, während das letztere zuerst den Datensatz mit DEPTNO=3 findet und vorwärts zum ersten Datensatz mit DEPT größer als 3 scannt.
(24) Verwenden Sie UNION-Ersetzungen OR (gilt für Indexspalten)
Normalerweise führt die Verwendung von UNION als Ersatz für OR in der WHERE-Klausel zu besseren Ergebnissen. Die Verwendung von OR für Indexspalten führt zu einem vollständigen Tabellenscan. Beachten Sie, dass die oben genannten Regeln nur für mehrere Indexspalten gültig sind. Wenn Spalten vorhanden sind, die nicht indiziert sind, kann die Abfrageeffizienz verringert werden, da Sie OR nicht auswählen. Im folgenden Beispiel werden Indizes sowohl auf LOC_ID als auch auf REGION erstellt. Effizient:
SELECT LOC_ID , LOC_DESC , REGION
VOM STANDORT
WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION
VOM STANDORT
WHERE REGION = „MELBOURNE“
Ineffizient:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10 OR REGION = „MELBOURNE“
Wenn Sie auf der Verwendung von OR bestehen, müssen Sie die Indexspalte mit den wenigsten Datensätzen zurückgeben und an den Anfang schreiben.
( 25) Verwenden Sie IN anstelle von OR
Dies ist eine einfache und leicht zu merkende Regel, aber der tatsächliche Ausführungseffekt muss unter ORACLE8i getestet werden. Die Ausführungspfade der beiden scheinen jedoch gleich zu sein.
Ineffizient:
SELECT…. VON STANDORT, WO LOC_ID = 10 ODER LOC_ID = 20 ODER LOC_ID = 30
Effizient
SELECT… VON STANDORT, WO LOC_IN IN (10,20,30);
(26) Vermeiden Sie die Verwendung von IS NULL und IS NOT NULL für Indexspalten.
Vermeiden Sie die Verwendung von Nullable-Spalten im Index, da ORACLE den Index nicht verwenden kann. Wenn bei einem einspaltigen Index eine Spalte einen Nullwert enthält, ist der Datensatz nicht im Index vorhanden. Wenn bei einem zusammengesetzten Index jede Spalte null ist, ist der Datensatz auch nicht im Index vorhanden nicht null ist, ist der Datensatz im Index vorhanden. Beispiel: Wenn ein eindeutiger Index für die Spalten A und B der Tabelle erstellt wird und es in der Tabelle einen Datensatz mit A- und B-Werten von (123, null) gibt, akzeptiert ORACLE den nächsten Datensatz mit demselben A nicht und B-Werte (123, null) Datensätze (Einfügung). Wenn jedoch alle Indexspalten null sind, betrachtet ORACLE den gesamten Schlüsselwert als null und null ist daher nicht gleich null 1000 Datensätze mit demselben Schlüsselwert, und natürlich sind sie alle null. Da der Nullwert in der Indexspalte nicht vorhanden ist, führt ein Nullwertvergleich der Indexspalte in der WHERE-Klausel dazu, dass ORACLE den Index deaktiviert 🎜>Ineffizienz: (Index ungültig)
SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;
Effizient: (Index gültig)
SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;
(27) Verwenden Sie immer die erste Spalte des Index:
Wenn der Index auf mehreren Spalten erstellt wird, verwendet der Optimierer den Index nur dann, wenn auf seine erste Spalte (führende Spalte) durch die where-Klausel verwiesen wird. Dies ist ebenfalls eine einfache aber wichtig: Wenn nur auf die zweite Spalte des Index verwiesen wird, verwendet seo/' target='_blank'> der Optimierer einen vollständigen Tabellenscan und ignoriert den Index
28) Ersetzen Sie UNION durch UNION-ALL (falls möglich):
Wenn eine SQL-Anweisung zwei UNION-Abfrageergebnismengen erfordert, werden die beiden Ergebnismengen auf UNION-ALL-Art zusammengeführt und dann vor der Ausgabe des Endergebnisses sortiert. Wenn UNION ALL anstelle von UNION verwendet wird Dadurch ist eine Sortierung nicht mehr erforderlich. Es ist zu beachten, dass UNION ALL immer wieder dieselben Datensätze in den beiden Ergebnismengen ausgibt. Daher müssen Sie noch die Machbarkeit der Verwendung von UNION ALL analysieren Basierend auf den Geschäftsanforderungen legt UNION die Sortierung fest. Die Optimierung dieses Speichers ist ebenfalls sehr wichtig. Die folgende SQL kann zum Abfragen des Sortierverbrauchs verwendet werden:
SELECT ACCT_NUM , BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
Effizient:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION ALL
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
(29) Ersetzen Sie ORDER BY durch WHERE: Die
ORDER BY-Klausel verwendet den Index nur unter zwei strengen Bedingungen.
ORDER BY Alle Spalten in ORDER BY müssen sein in denselben Index aufgenommen werden und die Reihenfolge im Index beibehalten.
Alle Spalten in ORDER BY müssen angegeben werden

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn