In MySQL bezieht sich der Hinweis auf einen „Abfrageoptimierungshinweis“, der den Optimierer auffordert, einen Ausführungsplan für die Optimierung auf eine bestimmte Weise zu generieren, wodurch die SQL-Anweisung des Benutzers flexibler wird. Der Hinweis kann auf der Verbindungssequenz und der Methode basieren Die Tabelle, Zugriffspfade, Parallelität und andere Regeln wirken sich auf DML-Anweisungen (Data Manipulation Language) aus.
Die Betriebsumgebung dieses Tutorials: Windows7-System, MySQL8-Version, Dell G3-Computer.
Wir können beim Betreiben von Tabellen, Feldern oder Indizes Kommentare hinzufügen, um die Lesbarkeit des Codes zu verbessern, damit andere den Code schnell verstehen können. Dies ist ein Tipp für Personen, die die Datenbank ebenfalls verwenden eine Eingabeaufforderung an die Datenbank.
Was ist ein Hinweis?
Ein Hinweis bezieht sich auf einen „Abfrageoptimierungshinweis“, der den Optimierer auffordert, auf eine bestimmte Weise zu optimieren, wodurch Ihre SQL-Anweisung flexibler wird, wodurch Ihre Abfrage schneller wird. Natürlich kann dies der Fall sein langsamer sein, es hängt alles von Ihrem Verständnis des Optimierers und Ihrem Verständnis des Szenarios ab.
Wir wissen, dass MySQL beim Ausführen einer SQL-Anweisung einen Ausführungsplan generiert und der Hinweis den Abfrageoptimierer anweist, den Ausführungsplan auf die von uns angegebene Weise zu generieren.
Hint kann auf DML-Anweisungen (Data Manipulation Language) basierend auf der Verbindungsreihenfolge, der Methode, dem Zugriffspfad, der Parallelität und anderen Regeln reagieren. Der Bereich ist wie folgt:
使用的优化器类型; 基于代价的优化器的优化目标,是all_rows还是first_rows; 表的访问路径,是全表扫描,还是索引扫描,还是直接用rowid; 表之间的连接类型; 表之间的连接顺序; 语句的并行程度;
Häufig verwendete Hinweise
Index erzwingen FORCE INDEXSELECT * FROM tbl FORCE INDEX (FIELD1) …
SELECT * FROM tbl FORCE INDEX (FIELD1) …
忽略索引 IGNORE INDEXSELECT * FROM tbl IGNORE INDEX (FIELD1, FIELD2) …
关闭查询缓冲 SQL_NO_CACHESELECT SQL_NO_CACHE field1, field2 FROM tbl;
需要查询实时数据且频率不高时,可以考虑把缓冲关闭,即不论此SQL是否曾被执行,MySQL都不会在缓冲区中查找。
强制查询缓冲 SQL_CACHESELECT SQL_CACHE * FROM tbl;
功能同上一条相反,但仅在my.ini中的query_cache_type设为2时起作用。
优先操作 HIGH_PRIORITY
HIGH_PRIORITY可以使用在select和insert操作中,让MYSQL知道,这个操作优先进行。SELECT HIGH_PRIORITY * FROM tbl;
滞后操作 LOW_PRIORITY
LOW_PRIORITY可以使用在insert和update操作中,让mysql知道,这个操作滞后。update LOW_PRIORITY tbl set field1= where field1= …
延时插入 INSERT DELAYEDINSERT DELAYED INTO tbl set field1= …
指客户端提交插入数据申请,MySQL返回OK状态却并未实际执行,而是存储在内存中排队,当mysql有空余时再插入。
一个重要的好处是,来自多个客户端的插入请求被集中在一起,编写入一个块,比独立执行许多插入要快很多。
坏处是,不能返回自增ID,以及系统崩溃时,MySQL还未来得及被插入的数据将会丢失。
强制连接顺序 STRAIGHT_JOINSELECT tbl.FIELD1, tbl2.FIELD2 FROM tbl STRAIGHT_JOIN tbl2 WHERE …
由上面的SQL语句可知,通过STRAIGHT_JOIN强迫MySQL按tbl、tbl2的顺序连接表。如果你认为按自己的顺序比MySQL推荐的顺序进行连接的效率高的话,就可以通过STRAIGHT_JOIN来确定连接顺序。
强制使用临时表 SQL_BUFFER_RESULTSELECT SQL_BUFFER_RESULT * FROM tbl WHERE …
当我们查询的结果集中的数据比较多时,可以通过SQL_BUFFER_RESULT.选项强制将结果集放到临时表中,这样就可以很快地释放MySQL的表锁(这样其它的SQL语句就可以对这些记录进行查询了),并且可以长时间地为客户端提供大记录集。
分组使用临时表 SQL_BIG_RESULT和SQL_SMALL_RESULTSELECT SQL_BUFFER_RESULT FIELD1, COUNT(*) FROM tbl GROUP BY FIELD1;
SELECT * FROM tbl IGNORE INDEX (FIELD1, FIELD2) …
🎜🎜🎜Schließen Sie den Abfragepuffer SQL_NO_CACHE🎜SELECT SQL_NO_CACHE field1, field2 FROM tbl;
🎜Wenn Sie Echtzeitdaten abfragen müssen und die Häufigkeit nicht hoch ist, können Sie Sie können in Betracht ziehen, den Puffer auszuschalten. Unabhängig davon, ob dieser SQL-Befehl jemals ausgeführt wurde, sucht MySQL nicht im Puffer. 🎜🎜🎜Abfragepufferung SQL_CACHE erzwingen🎜SELECT SQL_CACHE * FROM tbl;
🎜Die Funktion ist das Gegenteil der vorherigen, funktioniert aber nur, wenn query_cache_type in my.ini auf 2 gesetzt ist . 🎜🎜🎜Prioritätsoperation HIGH_PRIORITY🎜HIGH_PRIORITY kann in Auswahl- und Einfügeoperationen verwendet werden, um MYSQL mitzuteilen, dass diese Operation Priorität hat. 🎜SELECT HIGH_PRIORITY * FROM tbl;
🎜🎜🎜Verzögerter Vorgang LOW_PRIORITY🎜LOW_PRIORITY kann in Einfüge- und Aktualisierungsvorgängen verwendet werden, um MySQL darüber zu informieren, dass dieser Vorgang verzögert ist. 🎜update LOW_PRIORITY tbl set field1= where field1= …
🎜🎜🎜Delayed insert INSERT DELAYED🎜INSERT DELAYED INTO tbl set field1= …
🎜bezieht sich auf den Client Senden Sie die Anwendung zum Einfügen von Daten. MySQL gibt den Status „OK“ zurück, wird jedoch nicht tatsächlich ausgeführt, sondern im Speicher gespeichert und in die Warteschlange gestellt und dann eingefügt, wenn MySQL frei ist. 🎜Ein wichtiger Vorteil besteht darin, dass Einfügungsanfragen von mehreren Clients gruppiert und in einen Block geschrieben werden, was viel schneller ist, als viele Einfügungen unabhängig voneinander durchzuführen. 🎜Der Nachteil besteht darin, dass die automatisch inkrementierte ID nicht zurückgegeben werden kann und bei einem Systemabsturz die Daten verloren gehen, für deren Einfügen MySQL noch keine Zeit hatte. 🎜🎜🎜Erzwingen Sie die Verbindungssequenz STRAIGHT_JOIN🎜SELECT tbl.FIELD1, tbl2.FIELD2 FROM tbl STRAIGHT_JOIN tbl2 WHERE…
🎜Aus der obigen SQL-Anweisung ist ersichtlich, dass STRAIGHT_JOIN zum Erzwingen verwendet wird MySQL zum Drücken von tbl, tbl2 Tabellen nacheinander verknüpfen. Wenn Sie der Meinung sind, dass es effizienter ist, in Ihrer eigenen Reihenfolge beizutreten als in der von MySQL empfohlenen Reihenfolge, können Sie STRAIGHT_JOIN verwenden, um die Verbindungsreihenfolge zu bestimmen. 🎜SELECT SQL_BUFFER_RESULT * FROM tbl WHERE…
🎜Wenn wir die Daten abfragen in der Ergebnismenge In vielen Fällen können Sie die Ergebnismenge über die Option SQL_BUFFER_RESULT in eine temporäre Tabelle übertragen, sodass die MySQL-Tabellensperre schnell aufgehoben werden kann (damit andere SQL-Anweisungen diese Datensätze abfragen können). Wird seit langem verwendet. Stellen Sie Kunden große Datensätze zur Verfügung. 🎜🎜🎜Gruppe mit temporären Tabellen SQL_BIG_RESULT und SQL_SMALL_RESULT🎜SELECT SQL_BUFFER_RESULT FIELD1, COUNT(*) FROM tbl GROUP BY FIELD1;
🎜Wirksam für SELECT-Anweisungen, weist MySQL an, GROUP BY und How zu optimieren Um die temporäre Tabellensortierung für DISTINCT-Abfragen zu verwenden, bedeutet dies, dass die Ergebnismenge klein ist und direkt in der temporären Tabelle im Speicher sortiert werden kann. Andernfalls ist eine temporäre Tabellensortierung auf der Festplatte erforderlich. 🎜SQL_CALC_FOUND_ROWS
Es handelt sich eigentlich nicht um eine Optimierer-Eingabeaufforderung und hat auch keinen Einfluss auf den Ausführungsplan des Optimierers. Es führt jedoch dazu, dass die von MySQL zurückgegebene Ergebnismenge die Gesamtzahl der von diesem Vorgang betroffenen Zeilen enthält, die mit kombiniert werden müssen FOUND_ROWS()
Kombinierte Verwendung. FOUND_ROWS()
联用。SQL_CALC_FOUND_ROWS
通知MySQL将本次处理的行数记录下来; FOUND_ROWS()
用于取出被记录的行数,可以应用到分页场景。
一般的分页写法为:先查总数,计算页数,再查询某一页的详情。SELECT COUNT(*) from tbl WHERE …
SELECT * FROM tbl WHERE … limit m,n
但借助SQL_CALC_FOUND_ROWS
,可以简化成如下写法:SELECT SQL_CALC_FOUND_ROWS * FROM tbl WHERE … limit m,n;
SELECT FOUND_ROWS();
第二条SELECT
将返回第一条SELECT
不带limit时的总行数,如此只需执行一次较耗时的复杂查询就可同时得到总行数。
LOCK IN SHARE MODE、 FOR UPDATE
同样的,这俩也不是优化提示,是控制SELECT语句的锁机制,只对行级锁有效,即InnoDB支持。
扩展知识:
概念和区别
SELECT ... LOCK IN SHARE MODE
添加的是IS锁(意向共享锁),即在符合条件的rows上都加了共享锁,其他session可读取记录,亦可继续添加IS锁,但无法修改,直到这个加锁的session done(否则直接锁等待超时)。
SELECT ... FOR UPDATE
添加的是IX锁(意向排它锁),即符合条件的rows上都加了排它,其他session无法给这些记录添加任何S锁或X锁。如果不存在一致性非锁定读的话,则其他session是无法读取和修改这些记录的,但innodb有非锁定读(快照读不需要加锁)。
因此,for update
的加锁方式只是比lock in share mode
的方式多阻塞了select...lock in share mode
的查询方式,并不会阻塞快照读。
应用场景
LOCK IN SHARE MODE
的适用于两张存在关系的表的写场景,以mysql官方例子来说,一个表是child表,一个是parent表,假设child表的某一列child_id映射到parent表的c_child_id列,从业务角度讲,此时直接insert一条child_id=100记录到child表是存在风险的,因为insert的同时可能存在parent表执行了删除c_child_id=100的记录,业务数据有不一致的风险。正确方法是先执行select * from parent where c_child_id=100 lock in share mode
,锁定parent表的这条记录,然后执行insert into child(child_id) values (100)
SQL_CALC_FOUND_ROWS
benachrichtigt MySQL, die Anzahl der verarbeiteten Zeilen dieses Mal aufzuzeichnen; FOUND_ROWS()
wird verwendet, um die Anzahl der aufgezeichneten Zeilen abzurufen und kann auf Paging-Szenarien angewendet werden.
SELECT COUNT(*) from tbl WHERE …
SELECT * FROM tbl WHERE … limit m,n
Aber mit Hilfe von SQL_CALC_FOUND_ROWS
, Es kann wie folgt vereinfacht werden:
SELECT SQL_CALC_FOUND_ROWS * FROM tbl WHERE … limit m,n;
🎜SELECT FOUND_ROWS();
🎜Der zweite SELECT
gibt zurück. Das erste SELECT
ist die Gesamtzahl der Zeilen ohne Begrenzung. Auf diese Weise müssen Sie nur eine komplexe und zeitaufwändige Abfrage ausführen, um die Gesamtzahl der Zeilen zu erhalten zur gleichen Zeit. 🎜🎜🎜🎜SPERREN IM SHARE-MODUS, FÜR UPDATE🎜In ähnlicher Weise sind diese beiden keine Optimierungstipps. Sie sind der Sperrmechanismus, der die SELECT-Anweisung steuert. Sie sind nur für Sperren auf Zeilenebene wirksam, was von InnoDB unterstützt wird. 🎜🎜🎜Wissen erweitern:🎜🎜Konzepte und Unterschiede🎜🎜SELECT ... LOCK IN SHARE MODE
fügt eine IS-Sperre (absichtliche gemeinsame Sperre) hinzu, d. h., gemeinsame Sperren werden zu qualifizierten Zeilen hinzugefügt und können weiterhin IS-Sperren hinzufügen bis die gesperrte Sitzung abgeschlossen ist (ansonsten läuft die Wartezeit für die direkte Sperre ab). 🎜🎜SELECT ... FOR UPDATE
Was hinzugefügt wird, ist eine IX-Sperre (Intention Exclusive Lock), das heißt, es wird exklusiv zu den Zeilen hinzugefügt, die die Bedingungen erfüllen. Andere Sitzungen können keine S-Sperre oder S-Sperre hinzufügen Sperre für diese Datensätze. Wenn es keinen konsistenten, nicht sperrenden Lesevorgang gibt, können andere Sitzungen diese Datensätze nicht lesen und ändern, aber innodb verfügt über einen nicht sperrenden Lesevorgang (Snapshot-Lesen erfordert keine Sperre). 🎜Daher blockiert die Sperrmethode for update
nur select...lock in share mode
mehr als die Methode lock in share mode
Blockiert das Lesen von Snapshots nicht. 🎜🎜Anwendungsszenarien🎜🎜LOCK IN SHARE MODE
eignet sich zum Schreiben von Szenarien, in denen zwei Tabellen eine Beziehung haben. Nehmen wir das offizielle Beispiel von MySQL, eine Tabelle ist eine untergeordnete Tabelle. Eine davon ist die übergeordnete Tabelle. Angenommen, eine bestimmte Spalte „child_id“ der untergeordneten Tabelle ist der Spalte „c_child_id“ der übergeordneten Tabelle zugeordnet. Aus geschäftlicher Sicht ist es riskant, zu diesem Zeitpunkt einen Datensatz „child_id=100“ direkt in die untergeordnete Tabelle einzufügen , da die übergeordnete Tabelle möglicherweise gleichzeitig mit der Einfügung vorhanden ist. Nach dem Löschen des Datensatzes mit c_child_id=100 besteht die Gefahr einer Inkonsistenz in den Geschäftsdaten. Die richtige Methode besteht darin, zuerst select * from parent where c_child_id=100 lock in share mode
auszuführen, diesen Datensatz in der übergeordneten Tabelle zu sperren und dann insert into child(child_id) Values auszuführen (100)
code>. 🎜🎜【Verwandte Empfehlung: 🎜MySQL-Video-Tutorial🎜】🎜Das obige ist der detaillierte Inhalt vonWas ist ein MySQL-Hinweis?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!