2022 SQL Optimization Daquan Zusammenfassung und detaillierte Erläuterung

1. Die Grundstruktur von MySQL

1) Schema der MySQL-Infrastruktur

Der Client auf der linken Seite kann als Client betrachtet werden. Es gibt viele Clients, wie das CMD Black Window, das wir häufig verwenden, die WorkBench, die wir häufig zum Lernen verwenden, und das Navicat-Tool, das Unternehmen häufig verwenden. Sie alle sind a Klient. Der rechte Stapel kann als Server (MySQL-Server) betrachtet werden Wir unterteilen Server in SQL-Layer und Storage-Engine-Layer.

Wenn die Daten abgefragt werden, werden sie an den Ausführenden zurückgegeben. Einerseits schreibt der Executor die Ergebnisse in den Abfrage-Cache, und wenn Sie das nächste Mal erneut abfragen, können Sie die Daten direkt aus dem Abfrage-Cache abrufen. Geben Sie andererseits das Ergebnis direkt an den Client zurück.

2) Die Engine, die die Datenbank abfragt

① Motoren zeigen;

② Variablen wie „%storage_engine%“ anzeigen;

3) Geben Sie die Speicher-Engine des Datenbankobjekts an

create table tb(
    id int(4) auto_increment,
    name varchar(5),
    dept varchar(5),
    primary key(id)
) engine=myISAM auto_increment=1 default charset=utf8;

2. SQL-Optimierung

1) Warum ist eine SQL-Optimierung erforderlich?

Beim Durchführen von Vorgängen wie z. B. Join-Abfragen und Unterabfragen für mehrere Tabellen ist die Ausführungszeit des Servers aufgrund der von Ihnen geschriebenen schlechten SQL-Anweisung zu lang, und wir warten zu lange auf die Ergebnisse. Darauf aufbauend müssen wir lernen, wie man SQL optimiert.

2) MySQL-Schreibprozess und -Parsing-Prozess

① Schreibvorgang

select dinstinct  ..from  ..join ..on ..where ..group by ..having ..order by ..limit ..

② Analyseprozess

from .. on.. join ..where ..group by ..having ..select dinstinct ..order by ..limit ..

Stellen Sie eine Website bereit, die den mysql-Parsing-Prozess beschreibt:

https://www.cnblogs.com/annsshadow/p/5037667.html

3) SQL-Optimierung - hauptsächlich um den Index zu optimieren

Um SQL zu optimieren, ist das Wichtigste, SQL-Indizes zu optimieren.

Indizes sind äquivalent zu Verzeichnissen von Wörterbüchern. Die Verwendung des Wörterbuchverzeichnisses zum Suchen chinesischer Zeichen entspricht der Verwendung des SQL-Index zum Suchen eines Datensatzes. Mit dem Index können Sie einen Datensatz einfach und schnell finden.

① Was ist ein Index?

Ein Index ist eine [Datenstruktur], die MySQL hilft, Daten effizient zu erhalten. Ein Index ist eine Baumstruktur, und [B+-Baum] wird im Allgemeinen in MySQL verwendet.

② Indexdarstellung (hier wird ein binärer Baum verwendet, um uns beim Verständnis des Index zu helfen)

Die Merkmale der Baumstruktur sind: Das untergeordnete Element ist kleiner als das übergeordnete Element und wird auf der linken Seite platziert; das untergeordnete Element, das größer als das übergeordnete Element ist, wird auf der rechten Seite platziert.

Dieses Diagramm soll uns nur helfen, den Index leicht zu verstehen.Wir werden die eigentliche Beschreibung von [B+-Baum] weiter unten erklären.

Wie finden Indizes Daten? Zwei Wörter [zeigen auf] In der obigen Abbildung haben wir der Altersspalte einen Index zugewiesen, der der Baumstruktur auf der rechten Seite ähnelt. Jeder Zeilendatensatz in der mysql-Tabelle hat eine Hardwareadresse, z. B. age=50 im Index, die auf die Kennung ("Hardwareadresse") der Zeile in der Quelltabelle zeigt. Das heißt, der Baumindex stellt eine Zuordnungsbeziehung mit der Hardwareadresse jeder Zeile in der Quelltabelle her. Wenn Sie einen Index angeben, wird diese Zuordnungsbeziehung ebenfalls hergestellt. Deshalb können wir die Quelltabelle schnell über den Index finden . Gründe dokumentiert in.

Nehmen Sie als Beispiel die Abfrageanweisung [select * from student where age=33]. Wenn wir keinen Index hinzufügen, wird die Quelltabelle von oben nach unten gescannt. Wenn die fünfte Zeile gescannt wird, wird das gesuchte Element gefunden, was insgesamt 5 Abfragen entspricht. Beim Hinzufügen des Index wird direkt in der Baumstruktur gesucht, ist 33 kleiner als 50, wird von links nach 23 abgefragt, ist 33 größer als 23, wird erneut nach rechts abgefragt, diesmal 33 gefunden und der gesamte Index endet Es wurden insgesamt 3 Suchen durchgeführt. Ist es sehr praktisch? Wenn wir zu diesem Zeitpunkt age=62 finden müssen, können Sie über die Änderung der Anzahl der Suchen vor und nach dem "Hinzufügen eines Index" nachdenken.

4) Nachteile der Indizierung

1. Wenn die Datenmenge groß ist, wird der Index sehr groß (natürlich ist er im Vergleich zur Quelltabelle immer noch ziemlich klein), und er muss auch im Speicher/auf der Festplatte gespeichert werden (normalerweise gespeichert in der Festplatte), die eine bestimmte Datenmenge belegen Speicherplatz/physikalischer Platz.

2. Indizes sind nicht für alle Situationen geeignet: a) eine kleine Datenmenge b) häufig geänderte Felder eignen sich nicht für die Indizierung c) selten verwendete Felder müssen nicht indiziert werden

3. Der Index verbessert die Effizienz der Datenabfrage, verringert jedoch die Effizienz des "Hinzufügens, Löschens und Modifizierens". Wenn der Index nicht verwendet wird, müssen wir nur die Quelltabelle bedienen, um die Daten hinzuzufügen, zu löschen und zu ändern. Wenn wir jedoch den Index hinzufügen, müssen wir nicht nur die Quelltabelle ändern, sondern auch den Index erneut ändern , was sehr lästig ist. Trotzdem ist das Hinzufügen eines Indexes eine gute Sache, weil das meiste, was wir verwenden, eine Abfrage ist und "Abfrage" einen großen Einfluss auf die Leistung des Programms hat.

5) Vorteile der Indizierung

1. Verbessern Sie die Abfrageeffizienz (reduzieren Sie die IO-Nutzung). Wenn der Index erstellt wird, wird die Anzahl der Abfragen reduziert.

2. Reduzieren Sie die CPU-Auslastung. Beispielsweise lädt eine Operation wie [...order by age desc], wenn kein Index hinzugefügt wird, die Quelltabelle für eine Sortieroperation in den Speicher, was viele Ressourcen verbraucht. Aber nachdem der Index verwendet wurde, ist der erste Index selbst kleiner, der zweite Index selbst sortiert, die Daten auf der linken Seite sind die kleinsten und die Daten auf der rechten Seite die größten.

6) B+ Baumdarstellung

Der Index in MySQL verwendet die B+-Baumstruktur.

Eine Anmerkung zu B+-Bäumen:

Zunächst einmal bezieht sich Btree im Allgemeinen auf [B+-Baum], und alle Daten werden in Blattknoten gespeichert. Für die obige Abbildung gehört die untere dritte Schicht zum Blattknoten, und der eigentliche Datenteil wird im Blattknoten gespeichert. Was ist also mit den Daten in den Schichten 1 und 2? Antwort: Es wird verwendet, um Zeigerblöcke zu teilen, z. B. P1, wenn es kleiner als 26 ist, P2, wenn es zwischen 26 und 30 liegt, und P3, wenn es größer als 30 ist.

Zweitens kann der dreischichtige [B+-Baum] Millionen von Daten speichern. Wie hast du so viele Daten bekommen? Erhöhen Sie die "Anzahl der Knoten". Wir haben nur drei Knoten im Graphen.

Schließlich beträgt die Anzahl der Abfragen von Daten in [B+-Baum] n-mal, und n repräsentiert die Höhe von [B+-Baum].

3. Klassifizierung und Erstellung von Indizes

1) Index-Klassifizierung

einwertiger Index

eindeutiger Index

zusammengesetzter Index

① Einwertiger Index

Erstellen Sie einen einwertigen Index mithilfe eines Felds in der Tabelle. Oft gibt es mehrere Felder in einer Tabelle, was bedeutet, dass jede Spalte tatsächlich einen Index erstellen kann, der nach unseren tatsächlichen Bedürfnissen erstellt wird. Ein weiterer zu beachtender Punkt ist, dass eine Tabelle mehrere "einwertige Indizes" erstellen kann.

Wenn eine Tabelle sowohl ein Altersfeld als auch ein Namensfeld hat, können wir einen einwertigen Index für das Alter bzw. den Namen erstellen, sodass eine Tabelle zwei einwertige Indizes hat.

② Eindeutiger Index

Es verwendet auch ein Feld in der Tabelle, um einen einwertigen Index zu erstellen, der sich von einem einwertigen Index unterscheidet: Die Daten in dem Feld, in dem der eindeutige Index erstellt wird, dürfen keine doppelten Werte haben. Wie beim Alter müssen viele Personen im gleichen Alter vorhanden sein, beim Namen müssen einige Personen den gleichen Namen haben, daher ist es nicht geeignet, einen "eindeutigen Index" zu erstellen. Wie die Nummern-ID und die Studentennummer-Sid ist sie für jeden unterschiedlich, sodass sie zum Erstellen eines eindeutigen Index verwendet werden kann.

③ Zusammengesetzter Index

Ein Index, der aus mehreren Spalten besteht. Wir erstellen zum Beispiel einen solchen „zusammengesetzten Index“ (Name, Alter), fragen zuerst den Index mit dem Namen ab, und wenn der Name gleich ist, filtern wir wieder nach dem Alter. Hinweis: Die Felder des zusammengesetzten Index müssen nicht aufgebraucht werden. Wenn wir das Namensfeld verwenden, um die gewünschten Ergebnisse zu indizieren, muss nicht erneut nach Alter gefiltert werden.

2) Erstellen Sie einen Index

① Grammatik

Syntax: Indextyp Indexname für Tabelle (Feld) erstellen;

Die Tabellenerstellungsanweisung lautet wie folgt:

Die Struktur der Abfragetabelle ist wie folgt:

② Die erste Möglichkeit, einen Index zu erstellen

Ⅰ Erstellen Sie einen einwertigen Index

create index dept_index on tb(dept);

II Einen eindeutigen Index erstellen: Hier gehen wir davon aus, dass die Werte im Namensfeld alle eindeutig sind

create unique index name_index on tb(name);

Ⅲ Zusammengesetzten Index erstellen

create index dept_name_index on tb(dept,name);

③ Die zweite Möglichkeit, einen Index zu erstellen

Löschen Sie zuerst den zuvor erstellten Index und führen Sie dann den Test dieser Indexerstellungsmethode durch;

Syntax: Tabelle ändern Tabellenname Index hinzufügen Typ Indexname (Feld)

Ⅰ Erstellen Sie einen einwertigen Index

alter table tb add index dept_index(dept);

II Einen eindeutigen Index erstellen: Hier gehen wir davon aus, dass die Werte im Namensfeld alle eindeutig sind

alter table tb add unique index name_index(name);

Ⅲ Zusammengesetzten Index erstellen

alter table tb add index dept_name_index(dept,name);

④ Ergänzende Erklärung

Wenn ein Feld der Primärschlüssel ist, dann ist das Feld standardmäßig der Primärschlüsselindex.

Primärschlüsselindizes und eindeutige Indizes sind sehr ähnlich. Derselbe Punkt: Die Daten in der Spalte können nicht denselben Wert haben; der Unterschiedspunkt: Der Primärschlüsselindex kann keinen Nullwert haben, aber der eindeutige Index kann einen Nullwert haben.

3) Indexlöschung und Indexabfrage

① Index löschen

Syntax: Index Indexname auf Tabellenname löschen;

drop index name_index on tb;

② Indexabfrage

Syntax: Index aus Tabellenname anzeigen;

show index from tb;

Das Ergebnis ist wie folgt:

4. Untersuchung von SQL-Leistungsproblemen

Menschliche Optimierung: Wir müssen EXPLAIN verwenden, um den Ausführungsplan von SQL zu analysieren. Der Ausführungsplan kann den SQL-Optimierer simulieren, um die SQL-Anweisung auszuführen, was uns helfen kann, die Qualität unserer eigenen SQL zu verstehen.

Automatische Optimierung des SQL-Optimierers: Als wir zum ersten Mal das Ausführungsprinzip von MySQL beschrieben haben, wussten wir bereits, dass MySQL über einen Optimierer verfügt Schreiben Sie eine bessere äquivalente SQL zur Ausführung.

Die automatische Optimierungsfunktion des SQL-Optimierers [beeinträchtigt] unsere menschliche Optimierungsfunktion. Wenn wir den SQL-Ausführungsplan überprüfen und er nicht gut geschrieben ist, optimieren wir unser eigenes SQL. Wenn wir denken, dass wir gut optimiert haben, wird der endgültige Ausführungsplan nicht gemäß unserer optimierten SQL-Anweisung ausgeführt, aber manchmal wird die optimierte SQL geändert und ausgeführt.

Die SQL-Optimierung ist ein probabilistisches Problem. Manchmal führt das System das Ergebnis gemäß unserem optimierten SQL aus (der Optimierer denkt, dass das, was Sie geschrieben haben, ähnlich ist, und wird Ihr SQL nicht berühren). Manchmal ändert der Optimierer unser optimiertes SQL noch, bevor er es ausführt.

1) Zeigen Sie den Ausführungsplan an

Syntax: Erklären + SQL-Anweisung

zB:Erkläre select * from tb;

2) Mehrere „Schlüsselwörter“, die Sie im „Ausführungsplan“ kennen müssen

ID: Nummer

select_type : Abfragetyp

Tisch: Tisch

Typ: der Typ

possible_keys : der für die Vorhersage verwendete Index

key : der tatsächlich verwendete Index

key_len : Die tatsächliche Länge des verwendeten Index

ref : eine Referenz zwischen Tabellen

rows : Die Datenmenge, die über den Index abgefragt wird

Extra : zusätzliche Informationen

Tabellenanweisung erstellen und Daten einfügen:

# 建表语句
create table course
(
    cid int(3),
    cname varchar(20),
    tid int(3)
);

create table teacher
(
    tid int(3),
    tname varchar(20),
    tcid int(3)
);

create table teacherCard
(
    tcid int(3),
    tcdesc varchar(200)
);

# 插入数据
insert into course values(1,'java',1);
insert into course values(2,'html',1);
insert into course values(3,'sql',2);
insert into course values(4,'web',3);

insert into teacher values(1,'tz',1);
insert into teacher values(2,'tw',2);
insert into teacher values(3,'tl',3);

insert into teacherCard values(1,'tzdesc') ;
insert into teacherCard values(2,'twdesc') ;
insert into teacherCard values(3,'tldesc') ;

3) Detaillierte Erläuterung häufiger Schlüsselwörter im Ausführungsplan erläutern

1) Anweisungen zur Verwendung des Schlüsselworts id

① Fall: Fragen Sie die Informationen des Lehrers ab, dessen Kursnummer 2 ist oder dessen Lehrerzertifikatsnummer 3 ist:

# 查看执行计划
explain select t.*
from teacher t,course c,teacherCard tc
where t.tid = c.tid and t.tcid = tc.tcid
and (c.cid = 2 or tc.tcid = 3);

Das Ergebnis ist wie folgt:

Fügen Sie als Nächstes einige Daten zur Lehrertabelle hinzu.

insert into teacher values(4,'ta',4);
insert into teacher values(5,'tb',5);
insert into teacher values(6,'tc',6);

Überprüfen Sie den Ausführungsplan erneut.

# 查看执行计划
explain select t.*
from teacher t,course c,teacherCard tc
where t.tid = c.tid and t.tcid = tc.tcid
and (c.cid = 2 or tc.tcid = 3);

Das Ergebnis ist wie folgt:

Die Reihenfolge der Ausführung der Tabelle, der Grund für die Änderung aufgrund der Änderung der Anzahl der Tabellen: Kartesisches Produkt.

a   b   c
2   3   4
最终:2 * 3 * 4  = 6 * 4 = 24
c   b   a
4   3   2
最终:4 * 3 * 2 = 12 * 2 = 24

Analyse: Die Anzahl der endgültigen Hinrichtungen, obwohl konsistent. Im Zwischenprozess gibt es jedoch eine temporäre Tabelle mit 6 und eine temporäre Tabelle mit 12. Offensichtlich ist 6 < 12. Für den Speicher ist es umso besser, je kleiner die Datenmenge ist, sodass der Optimierer definitiv die erste Ausführungsreihenfolge wählt .

Fazit: Die id-Werte sind gleich und werden sequentiell von oben nach unten ausgeführt. Die Ausführungsreihenfolge der Tabellen ändert sich, wenn sich die Anzahl der Tabellen ändert.

② Fall: Abfrage der Beschreibung des Lehrers, der SQL-Kurse unterrichtet (desc)

# 查看执行计划
explain select tc.tcdesc from teacherCard tc 
where tc.tcid = 
(
    select t.tcid from teacher t 
    where  t.tid =  
    (select c.tid from course c where c.cname = 'sql')
);

Das Ergebnis ist wie folgt:

Fazit: Der ID-Wert ist unterschiedlich, je größer der ID-Wert, desto besser die Abfrage. Dies liegt daran, dass beim Ausführen von verschachtelten Unterabfragen zuerst die innere Ebene und dann die äußere Ebene überprüft wird.

③ Nehmen Sie eine einfache Änderung an ② vor

# 查看执行计划
explain select t.tname ,tc.tcdesc from teacher t,teacherCard tc 
where t.tcid= tc.tcid
and t.tid = (select c.tid from course c where cname = 'sql') ;

Das Ergebnis ist wie folgt:

Fazit: Die id-Werte sind gleich und unterschiedlich. Je größer der ID-Wert, desto höher die Priorität; derselbe ID-Wert wird in der Reihenfolge von oben nach unten ausgeführt.

2) Anweisungen für die Verwendung des Schlüsselworts select_type: Abfragetyp

① einfach: einfache Abfrage

Enthält keine Unterabfragen, enthält keine Union-Abfragen.

explain select * from teacher;

Das Ergebnis ist wie folgt:

② primär: die Hauptabfrage (äußerste Schicht), die die Unterabfrage enthält

③ Unterabfrage: die Hauptabfrage, die die Unterabfrage enthält (nicht die äußerste Schicht)

④ abgeleitet: abgeleitete Abfrage (temporäre Tabelle wird verwendet)

a) In der from-Unterabfrage gibt es nur eine Tabelle;

b) Wenn in der from-Unterabfrage Tabelle1 mit Tabelle2 verknüpft ist, dann ist Tabelle1 die abgeleitete Tabelle;

explain select  cr.cname     
from ( select * from course where tid = 1  union select * from course where tid = 2 ) cr ;

Das Ergebnis ist wie folgt:

⑤ Vereinigung: Die Tabelle nach der Vereinigung wird wie im obigen Beispiel Vereinigungstabelle genannt

⑥ Union-Ergebnis: Teilen Sie uns mit, welche Tabellen Union-Abfragen verwenden

3) Anleitung zur Verwendung des Schlüsselworts type: index type

system und const sind nur ideal und können nur auf die Ebene index --> range --> ref optimiert werden. Die Voraussetzung für die Optimierung des Typs ist, dass Sie einen Index erstellen müssen.

① System

Die Quelltabelle enthält nur ein Datenelement (in der Praxis ist dies im Grunde unmöglich);

Die abgeleitete Tabelle hat nur eine Hauptabfrage von Daten (die gelegentlich erreichbar ist).

② konst

SQL, das nur ein Datenelement finden kann, ist nur für Primärschlüssel oder eindeutige Indextypen gültig.

explain select tid from test01 where tid =1 ;

Das Ergebnis ist wie folgt:

Nachdem wir den vorherigen Primärschlüsselindex gelöscht haben, fügen wir zu diesem Zeitpunkt einen anderen gewöhnlichen Index hinzu:

create index test01_index on test01(tid) ;
# 再次查看执行计划
explain select tid from test01 where tid =1 ;

Das Ergebnis ist wie folgt:

③ eq_ref

Der eindeutige Index gibt für jede Indexschlüsselabfrage übereinstimmende eindeutige Zeilendaten zurück (es gibt nur eine, nicht mehr, keine 0), und das Abfrageergebnis und die Anzahl der Daten müssen konsistent sein.

Diese Situation ist bei eindeutigen Indizes und Primärschlüsselindizes üblich.

delete from teacher where tcid >= 4;
alter table teacherCard add constraint pk_tcid primary key(tcid);
alter table teacher add constraint uk_tcid unique index(tcid) ;
explain select t.tcid from teacher t,teacherCard tc where t.tcid = tc.tcid ;

Das Ergebnis ist wie folgt:

Zusammenfassung: In der obigen SQL ist der verwendete Index t.tcid, das ist das tcid-Feld in der Lehrertabelle; wenn die Anzahl der Daten in der Lehrertabelle dieselbe ist wie die Anzahl der Daten in der Verbindungsabfrage (beide sind 3 Datenstückchen), ist es möglich, eq_ref level zu erfüllen, andernfalls kann es nicht erfüllt werden. Die Bedingungen sind hart und schwer zu erreichen.

④ Ref

Nicht eindeutiger Index, gibt für jede Indexschlüsselabfrage alle übereinstimmenden Zeilen zurück (kann 0 sein, kann 1 sein, kann mehr sein)

Daten vorbereiten:

Erstellen Sie einen Index und zeigen Sie den Ausführungsplan an:

# 添加索引
alter table teacher add index index_name (tname) ;
# 查看执行计划
explain select * from teacher     where tname = 'tz';

Das Ergebnis ist wie folgt:

⑤ Bereich

Rufen Sie den angegebenen Zeilenbereich ab, wobei eine Bereichsabfrage folgt (zwischen, >, <, >=, in)

in schlägt manchmal fehl und wird daher zu ALL, wenn kein Index vorhanden ist

# 添加索引
alter table teacher add index tid_index (tid) ;
# 查看执行计划:以下写了一种等价SQL写法,查看执行计划
explain select t.* from teacher t where t.tid in (1,2) ;
explain select t.* from teacher t where t.tid <3 ;

Das Ergebnis ist wie folgt:

⑥ Index

Daten in allen Indizes abfragen (gesamten Index scannen)

⑦ ALLE

Daten in allen Quelltabellen abfragen (Brute Force Scan Full Table)

Hinweis: cid ist ein Indexfeld. Um das Indexfeld abzufragen, müssen Sie also nur die Indextabelle scannen. tid ist jedoch kein indiziertes Feld. Das Abfragen von nicht indizierten Feldern erfordert ein Brute-Force-Scannen der gesamten Quelltabelle, was mehr Ressourcen verbraucht.

4) Mögliche_Schlüssel und Schlüssel

possible_keys Indizes, die verwendet werden können. Es ist eine Vorhersage, nicht sicher. Finde es einfach heraus.

Schlüssel bezieht sich auf den tatsächlich verwendeten Index.

# 先给course表的cname字段,添加一个索引
create index cname_index on course(cname);
# 查看执行计划
explain select t.tname ,tc.tcdesc from teacher t,teacherCard tc
where t.tcid= tc.tcid
and t.tid = (select c.tid from course c where cname = 'sql') ;

Das Ergebnis ist wie folgt:

Beachten Sie, dass der Index nutzlos ist, wenn possible_key/key NULL ist.

5) key_len

Die Länge des Index, die verwendet wird, um zu bestimmen, ob der zusammengesetzte Index vollständig verwendet wird (a,b,c).

① Erstellen Sie eine neue Tabelle zum Testen

# 创建表
create table test_kl
(
    name char(20) not null default ''
);
# 添加索引
alter table test_kl add index index_name(name) ;
# 查看执行计划
explain select * from test_kl where name ='' ; 

Das Ergebnis ist wie folgt:

Ergebnisanalyse: Da ich den Zeichensatz des Servers nicht eingestellt habe, ist der Standardzeichensatz latin1. Für latin1 stellt ein Zeichen ein Byte dar, daher ist die Länge von key_len in dieser Spalte 20, was darauf hinweist, dass der Index von name verwendet wird .

② Fügen Sie der Tabelle test_kl die Spalte name1 hinzu, die nicht auf „not null“ gesetzt ist.

Das Ergebnis ist wie folgt:

Ergebnisanalyse: Wenn das Indexfeld null sein kann, verwendet die unterste Schicht von MySQL 1 Byte zur Identifizierung.

③ Löschen Sie den ursprünglichen Indexnamen und name1 und fügen Sie einen zusammengesetzten Index hinzu

# 删除原来的索引name和name1
drop index index_name on test_kl ;
drop index index_name1 on test_kl ;
# 增加一个复合索引 
create index name_name1_index on test_kl(name,name1);
# 查看执行计划
explain select * from test_kl where name1 = '' ; --121
explain select * from test_kl where name = '' ; --60

Das Ergebnis ist wie folgt:

Analyse der Ergebnisse: Für den folgenden Ausführungsplan können wir sehen, dass wir nur den ersten Indexfeldnamen des zusammengesetzten Index verwenden, also ist key_len 20, was sehr klar ist. Wenn Sie sich den obigen Ausführungsplan ansehen, verwenden wir zwar nur das Feld name1 im zusammengesetzten Indexfeld nach wo, aber wenn Sie das zweite Indexfeld des zusammengesetzten Index verwenden möchten, wird standardmäßig der Name des ersten Indexfelds des zusammengesetzten Index verwendet Da name1 null sein kann, ist key_len = 20 + 20 + 1 = 41!

④ So fügen Sie ein Name2-Feld erneut hinzu und erstellen einen Index für dieses Feld.

Der Unterschied ist: Der Felddatentyp ist varchar

# 新增一个字段name2,name2可以为null
alter table test_kl add column name2 varchar(20) ; 
# 给name2字段,设置为索引字段
alter table test_kl add index name2_index(name2) ;
# 查看执行计划
explain select * from test_kl where name2 = '' ;  

Das Ergebnis ist wie folgt:

Analyse der Ergebnisse: key_len = 20 + 1 + 2, wir kennen diese 20 + 1, was bedeutet diese 2? Es stellt sich heraus, dass varchar eine variable Länge hat.In der untersten Schicht von mysql werden 2 Bytes verwendet, um die variable Länge zu identifizieren.

6)ref

Die Rolle von ref gibt hier das Feld an, auf das von der aktuellen Tabelle verwiesen wird.

Beachten Sie, dass es sich vom ref-Wert im Typ unterscheidet. In type ist ref nur ein Optionswert vom Typ type.

# 给course表的tid字段,添加一个索引
create index tid_index on course(tid);
# 查看执行计划
explain select * from course c,teacher t 
where c.tid = t.tid  
and t.tname = 'tw';

Das Ergebnis ist wie folgt:

Analyse der Ergebnisse: Es gibt zwei Indizes: Die c.tid der c-Tabelle bezieht sich auf das tid-Feld der t-Tabelle, sodass Sie sehen können, dass das Anzeigeergebnis [Datenbankname.t.tid] ist, und die t. Der Name der t-Tabelle bezieht sich auf eine Konstante „tw“, sodass Sie sehen können, dass das Ergebnis als const angezeigt wird, was eine Konstante bedeutet.

7) Zeilen (das ist noch ein wenig zweifelhaft)

Die Anzahl der von der Indexoptimierung abgefragten Daten (die Anzahl der tatsächlich über den Index abgefragten Daten)

explain select * 
from course c,teacher t  
where c.tid = t.tid
and t.tname = 'tz' ;

Das Ergebnis ist wie folgt:

8)zusätzlich

Es ist auch nützlich, einige andere Anweisungen anzugeben.

① mit Filesort: für den Fall eines einzelnen Indexes

Wenn dieses Wort erscheint, bedeutet dies, dass Ihre aktuelle SQL-Leistung viel verbraucht. Zeigt an, dass eine "zusätzliche" Sortierung durchgeführt wurde. Wird häufig in order by-Anweisungen verwendet.

Ⅰ Was ist eine „Extra“-Sortierung?

Um dies zu verdeutlichen, müssen wir zunächst wissen, was Sortieren ist. Wenn wir ein Feld sortieren wollen, müssen Sie zuerst dieses Feld abfragen und dann dieses Feld sortieren.

Als nächstes sehen wir uns die Ausführungspläne der folgenden zwei SQL-Anweisungen an.

# 新建一张表,建表同时创建索引
create table test02
(
    a1 char(3),
    a2 char(3),
    a3 char(3),
    index idx_a1(a1),
    index idx_a2(a2),
    index idx_a3(a3)
);
# 查看执行计划
explain select * from test02 where a1 ='' order by a1 ;
explain select * from test02 where a1 ='' order by a2 ; 

Das Ergebnis ist wie folgt:

Analyse der Ergebnisse: Für den ersten Ausführungsplan fragen wir nach where zuerst das a1-Feld ab und verwenden dann a1, um in der Reihenfolge zu sortieren, was sehr einfach ist. Aber für den zweiten Ausführungsplan fragen wir das a1-Feld nach dem where ab, aber das a2-Feld wird zum Sortieren verwendet. Zu diesem Zeitpunkt führt die unterste Ebene von myql eine Abfrage durch, um eine „zusätzliche“ Sortierung durchzuführen.

Zusammenfassung: Wenn bei einem einzelnen Index Sortieren und Suchen dasselbe Feld sind, wird Filesort nicht verwendet; wenn Sortieren und Suchen nicht dasselbe Feld sind, wird Filesort verwendet; also wo Felder sind, nach welchen Feldern sortieren.

② mit Filesort: für zusammengesetzte Indizes

kann sich nicht über Spalten erstrecken (offizieller Begriff: bestes linkes Präfix)

# 删除test02的索引
drop index idx_a1 on test02;
drop index idx_a2 on test02;
drop index idx_a3 on test02;
# 创建一个复合索引
alter table test02 add index idx_a1_a2_a3 (a1,a2,a3) ;
# 查看下面SQL语句的执行计划
explain select *from test02 where a1='' order by a3 ;  --using filesort
explain select *from test02 where a2='' order by a3 ; --using filesort
explain select *from test02 where a1='' order by a2 ;

Das Ergebnis ist wie folgt:

Analyse der Ergebnisse: Die Reihenfolge des zusammengesetzten Indexes ist (a1, a2, a3). Sie können sehen, dass sich a1 ganz links befindet, also wird a1 das „beste linke Präfix“ genannt. Wenn Sie den folgenden Index verwenden möchten Felder müssen Sie zuerst dieses a1-Feld verwenden. Für „explain1“ verwenden wir das Feld „a1“ nach „where“, aber die nachfolgende Sortierung verwendet „a3“, wodurch a2 direkt übersprungen wird, das zu „cross-column“ gehört; für „explain2“ verwenden wir das Feld „a2“ nach „where“, überspringt direkt das Feld „a1“ und gehört ebenfalls dazu to cross-column ; Für explain3 verwenden wir das a1-Feld nach where und das a2-Feld, also gibt es kein [using filesort].

③ mit temporären

Wenn dieses Wort erscheint, bedeutet dies auch, dass Ihre aktuelle SQL-Leistung viel verbraucht. Dies liegt daran, dass das aktuelle SQL temporäre Tabellen verwendet. Erscheint normalerweise in Gruppieren nach.

explain select a1 from test02 where a1 in ('1','2','3') group by a1 ;
explain select a1 from test02 where a1 in ('1','2','3') group by a2 ; --using temporary

Das Ergebnis ist wie folgt:

Ergebnisanalyse: Wenn Sie nach welchem ​​Feld fragen, gruppieren Sie nach diesem Feld, andernfalls wird die Verwendung von temporäre angezeigt.

Für die Verwendung von temporär sehen wir uns ein Beispiel an:

Die Verwendung von Temporary zeigt an, dass eine zusätzliche Tabelle verwendet werden muss, die im Allgemeinen in der group by-Anweisung erscheint. Obwohl bereits eine Tabelle vorhanden ist, ist sie nicht anwendbar, und es muss eine weitere Tabelle erstellt werden.

Schauen wir uns noch einmal den Schreib- und Parsing-Prozess von mysql an.

Ⅰ Schreibprozess

select dinstinct  ..from  ..join ..on ..where ..group by ..having ..order by ..limit ..

Ⅱ Analytischer Prozess

from .. on.. join ..where ..group by ..having ..select dinstinct ..order by ..limit ..

Offensichtlich, nachdem wo gruppiert ist, und dann auswählen. Sehen wir uns auf dieser Grundlage die Ausführungspläne der folgenden beiden SQL-Anweisungen an.

explain select * from test03 where a2=2 and a4=4 group by a2,a4;
explain select * from test03 where a2=2 and a4=4 group by a3;

Die Analyse ist wie folgt: Für den ersten Ausführungsplan, wo folgt a2 und a4, und dann gruppieren wir nach a2 und a4 Offensichtlich existieren diese beiden Tabellen bereits, und wir können sie direkt auf a2 und a4 gruppieren. Aber für den zweiten Ausführungsplan folgen a2 und a4, und dann gruppieren wir nach a3. Offensichtlich haben wir die a3-Tabelle nicht, also brauchen wir eine weitere temporäre Tabelle a3. Es wird also eine vorübergehende Verwendung geben.

④ mit Index

Wenn Sie dieses Schlüsselwort sehen, herzlichen Glückwunsch, bedeutet dies, dass sich Ihre SQL-Leistung verbessert hat.

Die Verwendung von Index nennt es "Indexabdeckung".

Wenn der Index verwendet wird, bedeutet dies, dass Sie die Quelltabelle nicht lesen müssen, sondern nur den Index verwenden müssen, um Daten abzurufen, und nicht die Quelltabelle zurückfragen müssen.

Solange die verwendeten Spalten alle im Index erscheinen, handelt es sich um eine Indexabdeckung.

# 删除test02中的复合索引idx_a1_a2_a3
drop index idx_a1_a2_a3 on test02;
# 重新创建一个复合索引idx_a1_a2
create index idx_a1_a2 on test02(a1,a2);
# 查看执行计划
explain select a1,a3 from test02 where a1='' or a3= '' ;
explain select a1,a2 from test02 where a1='' and a2= '' ;

Das Ergebnis ist wie folgt:

Ergebnisanalyse: Wir haben einen zusammengesetzten Index aus a1 und a2 erstellt. Für den ersten Ausführungsplan haben wir a3. Dieses Feld erstellt keinen Index, daher gibt es keinen using-Index, sondern using where, was darauf hinweist, dass wir zu zurückkehren müssen Tisch. Für den zweiten Ausführungsplan handelt es sich um eine vollständige Indexabdeckung, sodass ein Verwendungsindex vorhanden ist.

Für die Verwendung von index betrachten wir einen Fall:

explain select a1,a2 from test02 where a1='' or a2= '' ;
explain select a1,a2 from test02;

Das Ergebnis ist wie folgt:

Wenn Indexabdeckung verwendet wird (bei Verwendung von Index), wirkt sich dies auf possible_keys und keys aus:

a. Wenn es kein wo gibt, erscheint der Index nur im Schlüssel;

b. Wenn es wo gibt, erscheint der Index in Schlüssel und möglichen_Schlüsseln.

⑤ mit wo

Gibt an, dass [return table query] erforderlich ist, was bedeutet, dass die Abfrage sowohl im Index als auch zurück zur Quelltabelle ausgeführt wird.

# 删除test02中的复合索引idx_a1_a2
drop index idx_a1_a2 on test02;
# 将a1字段,新增为一个索引
create index a1_index on test02(a1);
# 查看执行计划
explain select a1,a3 from test02 where a1="" and a3="" ;

Das Ergebnis ist wie folgt:

Analyse der Ergebnisse: Wir verwenden beide den Index a1, was bedeutet, dass wir den Index zum Abfragen verwenden. Aber für das a3-Feld haben wir den Index nicht verwendet, also müssen wir für das a3-Feld die Quelltabelle zurückfragen und verwenden, wo zu diesem Zeitpunkt erscheint.

⑥ unmöglich wo (verstehen)

Unmöglich, wo auftritt, wenn die where-Klausel immer falsch ist

# 查看执行计划
explain select a1 from test02 where a1="a" and a1="b" ;

Das Ergebnis ist wie folgt:

6. Optimierungsbeispiel

1) Stellen Sie den Fall vor

# 创建新表
create table test03
(
    a1 int(4) not null,
    a2 int(4) not null,
    a3 int(4) not null,
    a4 int(4) not null
);
# 创建一个复合索引
create index a1_a2_a3_test03 on test03(a1,a2,a3);
# 查看执行计划
explain select a3 from test03 where a1=1 and a2=2 and a3=3;

Das Ergebnis ist wie folgt:

Empfohlene Schreibmethode: Die Reihenfolge der zusammengesetzten Indizes entspricht der Reihenfolge der Verwendung.

Werfen wir einen Blick auf [Nicht empfohlene Schreibmethode]: Die Reihenfolge des zusammengesetzten Index stimmt nicht mit der Reihenfolge der Verwendung überein.

# 查看执行计划
explain select a3 from test03 where a3=1 and a2=2 and a1=3;

Das Ergebnis ist wie folgt:

Analyse der Ergebnisse: Obwohl die Ergebnisse mit den obigen Ergebnissen übereinstimmen, wird es nicht empfohlen, auf diese Weise zu schreiben. Aber warum ist es kein Problem, es so zu schreiben? Dies liegt an der Arbeit des SQL-Optimierers, der die Reihenfolge für uns angepasst hat.

Eine letzte Sache, die hinzugefügt werden muss: Verwenden Sie für zusammengesetzte Indizes nicht spaltenübergreifend

# 查看执行计划
explain select a3 from test03 where a1=1 and a3=2 group by a3;

Das Ergebnis ist wie folgt:

Ergebnisanalyse: a1_a2_a3 ist ein zusammengesetzter Index. Nachdem wir den a1-Index verwendet haben, verwenden wir direkt a3 über die Spalten hinweg und überspringen den Index a2 direkt. Daher ist der Index a3 ungültig. Wenn a3 zum Gruppieren verwendet wird, erscheint die Verwendung von where.

2) Einzeltabellenoptimierung

# 创建新表
create table book
(
        bid int(4) primary key,
        name varchar(20) not null,
        authorid int(4) not null,
        publicid int(4) not null,
        typeid int(4) not null 
);
# 插入数据
insert into book values(1,'tjava',1,1,2) ;
insert into book values(2,'tc',2,1,2) ;
insert into book values(3,'wx',3,2,1) ;
insert into book values(4,'math',4,2,3) ;    

Das Ergebnis ist wie folgt:

Fall: Gebote mit authorid=1 und typeid 2 oder 3 abfragen und absteigend nach typeid sortieren.

explain 
select bid from book 
where typeid in(2,3) and authorid=1  
order by typeid desc ;    

Das Ergebnis ist wie folgt:

Dies ist SQL ohne jegliche Optimierung. Sie können sehen, dass typ ALL ist und extra filesort verwendet. Sie können sich vorstellen, wie schrecklich dieses SQL ist.

Optimierung: Wenn Sie einen Index hinzufügen, sollte der Index gemäß der MySQL-Parsing-Reihenfolge hinzugefügt werden, was wiederum der MySQL-Parsing-Reihenfolge entspricht.

from .. on.. join ..where ..group by ..having ..select dinstinct ..order by ..limit ..

① Optimierung 1: Darauf aufbauend fügen wir den Index hinzu und prüfen den Ausführungsplan erneut.

# 添加索引
create index typeid_authorid_bid on book(typeid,authorid,bid);
# 再次查看执行计划
explain 
select bid from book 
where typeid in(2,3) and authorid=1  
order by typeid desc ;

Das Ergebnis ist wie folgt:

Analyse der Ergebnisse: Das Ergebnis ist nicht so, wie wir es uns vorgestellt haben, es gibt immer noch eine Verwendung von where, überprüfen Sie die Indexlänge key_len=8, was bedeutet, dass wir nur 2 Indizes verwenden und ein Index ungültig ist.

② Optimierung 2: Die Verwendung von in führt manchmal dazu, dass der Index fehlschlägt Darauf aufbauend gibt es folgende Optimierungsidee.

Setzen Sie das In-Feld am Ende. Eine Sache zu beachten: Jedes Mal, wenn ein neuer Index erstellt wird, ist es am besten, den vorherigen aufgegebenen Index zu löschen, da es sonst manchmal zu Interferenzen (zwischen Indizes) kommt.

# 删除以前的索引
drop index typeid_authorid_bid on book;
# 再次创建索引
create index authorid_typeid_bid on book(authorid,typeid,bid);
# 再次查看执行计划
explain 
select bid from book 
where authorid=1  and typeid in(2,3)  
order by typeid desc ;

Das Ergebnis ist wie folgt:

Analyse der Ergebnisse: Hier gibt es zwar keine Änderung, aber es handelt sich um eine Optimierungsidee.

Zusammengefasst wie folgt:

a. Es ist am besten, Präfixe zu verwenden, um die Reihenfolge in der Definition und Verwendung von Indizes konsistent zu halten

b. Der Index muss schrittweise optimiert werden (jedes Mal, wenn ein neuer Index erstellt wird, muss der zuvor aufgegebene Index der Situation entsprechend gelöscht werden).

c. Setzen Sie die Bereichsabfrage, die In enthält, an das Ende der where-Bedingung, um eine Ungültigkeitserklärung zu verhindern.

In diesem Beispiel: Using where (erfordert die Rückkehr zur ursprünglichen Tabelle); Using index (muss nicht zur ursprünglichen Tabelle zurückkehren): Reason, wobei authorid=1 und typeid in (2,3), authorid is in the index ( authorid, typeid, bid) , sodass man nicht auf die ursprüngliche Tabelle zurückgreifen muss (sie ist direkt in der Indextabelle zu finden); und obwohl typeid auch im Index steht (authorid, typeid, bid), die Bereichsabfrage enthält in hat den Typ-ID-Index ungültig gemacht, also ist es äquivalent zu Es gibt keinen Index von Typ-ID, also müssen Sie zur ursprünglichen Tabelle zurückkehren (unter Verwendung von where);

Ohne In gibt es beispielsweise kein using where:

explain select bid from book 
where  authorid=1 and typeid =3
order by typeid desc ;

Das Ergebnis ist wie folgt:

3) Zwei-Tabellen-Optimierung

# 创建teacher2新表
create table teacher2
(
        tid int(4) primary key,
        cid int(4) not null
);
# 插入数据
insert into teacher2 values(1,2);
insert into teacher2 values(2,1);
insert into teacher2 values(3,3);
# 创建course2新表
create table course2
(
    cid int(4) ,
    cname varchar(20)
);
# 插入数据
insert into course2 values(1,'java');
insert into course2 values(2,'python');
insert into course2 values(3,'kotlin');

Beispiel: Verwenden Sie einen linken Join, um alle Informationen zum Unterrichten einer Java-Klasse zu finden.

explain 
select *
from teacher2 t 
left outer join course2 c
on t.cid=c.cid 
where c.cname='java';

Das Ergebnis ist wie folgt:

① Optimierung

Wo sollte bei zwei Tabellen der Index hinzugefügt werden? A: Bei Tabellenverknüpfungen steuern kleine Tabellen große Tabellen. Indizes basieren auf häufig verwendeten Feldern.

Warum ist es besser, wenn ein kleiner Tisch einen großen Tisch antreibt?

    小表:10
    大表:300
# 小表驱动大表
select ...where 小表.x10=大表.x300 ;
for(int i=0;i<小表.length10;i++)
{
    for(int j=0;j<大表.length300;j++)
    {
        ...
    }
}
# 大表驱动小表
select ...where 大表.x300=小表.x10 ;
for(int i=0;i<大表.length300;i++)
{
    for(int j=0;j<小表.length10;j++)
    {
        ...
    }
}

Analyse: Die beiden obigen FOR-Schleifen werden schließlich 3000 Mal durchlaufen, aber für Doppelschicht-Schleifen: Es wird allgemein empfohlen, die Schleife mit kleinen Daten in der äußeren Schicht zu platzieren. Legen Sie Schleifen mit großen Datenmengen in die innere Ebene. Unabhängig vom Grund ist dies ein Prinzip von Programmiersprachen: Je weniger Außenschleifen und je größer die Speicherschleifen, desto höher ist die Leistung des Programms.

Fazit: Wenn Sie […on t.cid=c.cid] schreiben, platzieren Sie die Tabelle mit einer kleinen Datenmenge auf der linken Seite (vorausgesetzt, die Datenmenge in der t-Tabelle ist klein und die Datenmenge in der c Tisch ist groß.)

Wir wissen bereits, dass wir für die Verbindung zweier Tabellen eine kleine Tabelle verwenden müssen, um eine große Tabelle zu steuern, z. B. […on t.cid=c.cid], wenn t eine kleine Tabelle (10 Einträge) ist, wenn c ist eine große Tabelle (300 Einträge), dann muss t 300 Mal für jeden Zyklus durchlaufen werden, d. h. das Feld t.cid der Tabelle t gehört zu den häufig verwendeten Feldern, daher muss ein Index hinzugefügt werden das cid-Feld.

Ausführlichere Erklärung: Im Allgemeinen indiziert ein Left Join die linke Tabelle. Ein Right Join indiziert die rechte Tabelle. Ob weitere Tabellen indiziert werden müssen, werden wir Schritt für Schritt ausprobieren.

# 给左表的字段加索引
create index cid_teacher2 on teacher2(cid);
# 查看执行计划
explain 
select *
from teacher2 t 
left outer join course2 c
on t.cid=c.cid 
where c.cname='java';

Das Ergebnis ist wie folgt:

Natürlich können Sie nach unten gehen und cname optimieren und einen Index hinzufügen. Die Indexoptimierung ist ein schrittweiser Prozess, der ein wenig Experimentieren erfordert.

# 给cname的字段加索引
create index cname_course2 on course2(cname);
# 查看执行计划
explain 
select t.cid,c.cname
from teacher2 t 
left outer join course2 c
on t.cid=c.cid 
where c.cname='java';

Das Ergebnis ist wie folgt:

Fügen Sie zum Schluss noch eins hinzu: Die Verwendung des Join-Puffers ist eine zusätzliche Option, was bedeutet, dass die MySQL-Engine den "Verbindungscache" verwendet, dh die unterste Ebene von MySQL verschiebt Ihr SQL und Ihr Schreiben ist zu schlecht.

4) Drei-Tabellen-Optimierung

  • Größer oder gleich einer Tabelle, das Optimierungsprinzip ist dasselbe

  • Kleiner Tisch treibt großen Tisch an

  • Indizes werden auf häufig abgefragten Feldern erstellt

7. Einige Prinzipien zur Vermeidung von Indexfehlern

① Hinweise zu zusammengesetzten Indizes

  • Zusammengesetzte Indizes, nicht spaltenübergreifend oder außerhalb der Reihenfolge verwenden (am besten linkes Präfix)

  • Versuchen Sie für zusammengesetzte Indizes, den vollständigen Indexabgleich zu verwenden, dh wenn Sie mehrere Indizes erstellen, verwenden Sie mehrere Indizes

② Führen Sie keine Operation (Berechnung, Funktion, Typkonvertierung) mit dem Index durch, da der Index sonst ungültig wird

explain select * from book where authorid = 1 and typeid = 2;
explain select * from book where authorid*2 = 1 and typeid = 2 ;

Das Ergebnis ist wie folgt:

③ Der Index darf nicht not equal (!= <>) oder is null (ist nicht null) verwenden, andernfalls sind er und alle rechten Seiten ungültig (in den meisten Fällen). Wenn der zusammengesetzte Index ein > enthält, sind der self- und der right-Index alle ungültig.

# 针对不是复合索引的情况
explain select * from book where authorid != 1 and typeid =2 ;
explain select * from book where authorid != 1 and typeid !=2 ;

Das Ergebnis ist wie folgt:

Sehen Sie sich diesen Fall noch einmal an:

# 删除单独的索引
drop index authorid_index on book;
drop index typeid_index on book;
# 创建一个复合索引
alter table book add index idx_book_at (authorid,typeid);
# 查看执行计划
explain select * from book where authorid > 1 and typeid = 2 ;
explain select * from book where authorid = 1 and typeid > 2 ;

Das Ergebnis ist wie folgt:

Fazit: Wenn der zusammengesetzte Index [>] enthält, sind der Index selbst und der rechte Index ungültig.

Sehen Sie sich den Fall an, in dem [<] im zusammengesetzten Index steht:

Wir lernen die Indexoptimierung, was eine Schlussfolgerung ist, die für die meisten Situationen gilt, aber aus Gründen wie dem SQL-Optimierer nicht 100% richtig ist. Im Allgemeinen Bereichsabfragen (>< in), danach wird der Index ungültig gemacht.

④ Die SQL-Optimierung ist eine Optimierung auf Wahrscheinlichkeitsebene. Ob unsere Optimierung tatsächlich zum Einsatz kommt, darüber muss Explain spekulieren.

# 删除复合索引
drop index authorid_typeid_bid on book;
# 为authorid和typeid,分别创建索引
create index authorid_index on book(authorid);
create index typeid_index on book(typeid);
# 查看执行计划
explain select * from book where authorid = 1 and typeid =2 ;

Das Ergebnis ist wie folgt:

Analyse der Ergebnisse: Wir haben zwei Indizes erstellt, aber nur ein Index wurde tatsächlich verwendet. Denn für zwei separate Indizes hält das Programm nur einen Index für ausreichend, und es besteht keine Notwendigkeit, zwei zu verwenden.

Wenn wir einen zusammengesetzten Index erstellen, führen Sie das obige SQL erneut aus:

# 查看执行计划
explain select * from book where authorid = 1 and typeid =2 ;

Das Ergebnis ist wie folgt:

⑤ Indexabdeckung, 100 % kein Problem

⑥ Versuchen Sie, mit "Konstante" zu beginnen, beginnen Sie nicht mit "%", da sonst der Index ungültig wird

explain select * from teacher where tname like "%x%" ;
explain select * from teacher  where tname like 'x%';
explain select tname from teacher  where tname like '%x%';

Das Ergebnis ist wie folgt:

Die Schlussfolgerung lautet wie folgt: Versuchen Sie, keine Fälle wie „%x%“ zu verwenden, aber „x%“-Fälle können verwendet werden. Wenn Sie „%x%“ nicht verwenden, müssen Sie die Indexabdeckung verwenden.

⑦ Versuchen Sie, keine Typkonvertierung (explizit, implizit) zu verwenden, da sonst der Index fehlschlägt

explain select * from teacher where tname = 'abc' ;
explain select * from teacher where tname = 123 ;

Das Ergebnis ist wie folgt:

⑧ Versuchen Sie, oder nicht zu verwenden, andernfalls schlägt der Index fehl

explain select * from teacher where tname ='' and tcid >1 ;
explain select * from teacher where tname ='' or tcid >1 ;

Das Ergebnis ist wie folgt:

Hinweis: or ist sehr gewalttätig, wodurch sowohl der eigene Index als auch die Indizes auf der linken und rechten Seite ungültig werden.

8. Einige andere Optimierungsmethoden

1) Optimierung von exist und in

Wenn der Datensatz der Hauptabfrage groß ist, wird das Schlüsselwort i verwendet, was effizienter ist.

Wenn der Datensatz der Unterabfrage groß ist, wird das Schlüsselwort exist verwendet, was effizienter ist.

select ..from table where exist (子查询) ;
select ..from table where 字段 in  (子查询) ;

2) Ordnung nach Optimierung

  • IO ist die Anzahl der Zugriffe auf die Festplattendatei

  • Die Verwendung von Filesort hat zwei Algorithmen: Zwei-Wege-Sortierung, Ein-Wege-Sortierung (gemäß der Anzahl der IOs)

  • Vor MySQL 4.1 wurde standardmäßig die Zwei-Wege-Sortierung verwendet; Zwei-Wege: Festplatte zweimal scannen (1: Sortierfeld von der Festplatte lesen, Sortierfeld sortieren (im Puffer sortieren) 2: andere Felder scannen)

  • Nach MySQL 4.1 wird standardmäßig eine Einwegsortierung verwendet: nur einmal lesen (alle Felder) und im Puffer sortieren. Eine Einwegsortierung birgt jedoch gewisse versteckte Gefahren (nicht unbedingt „Einweg/1 IO“, es kann mehrere IOs geben). Grund: Wenn die Datenmenge besonders groß ist, können nicht die Daten aller Felder auf einmal gelesen werden, daher wird „Shard-Read, Multiple-Read“ durchgeführt.

  • Hinweis: Die unidirektionale Sortierung benötigt mehr Puffer als die bidirektionale Sortierung.

  • Wenn die Sortierung in eine Richtung verwendet wird und die Daten groß sind, können Sie die Größe des Puffers erhöhen:

# 不一定真的是“单路/1次IO”,有可能多次IO
set max_length_for_sort_data = 1024 

Wenn der Wert für max_length_for_sort_data zu niedrig ist, geht mysql automatisch von unidirektional -> bidirektional (zu niedrig: Die Gesamtgröße der Spalten, die sortiert werden müssen, überschreitet die Anzahl von Bytes, die durch max_length_for_sort_data definiert ist).

① Verbesserung der Order-by-Query-Strategie:

  • Wählen Sie, ob Sie Single-Channel oder Dual-Channel verwenden möchten, und passen Sie die Kapazität des Puffers an

  • Vermeiden Sie die Verwendung von select * ... (schreiben Sie alle Felder nach select, was auch effizienter ist als das Schreiben von *)

  • Zusammengesetzter Index, nicht spaltenübergreifend verwenden, Filesort vermeiden, um alle Sortierfelder sicherzustellen, Sortierkonsistenz (sowohl aufsteigende als auch absteigende Reihenfolge)

Supongo que te gusta

Origin blog.csdn.net/ytp552200ytp/article/details/126122668
Recomendado
Clasificación