Schnellste Löschgeschwindigkeit |
|
Wenn eine Tabelle nicht mehr benötigt wird, verwenden Sie „drop“; wenn Sie einige Datenzeilen löschen möchten, verwenden Sie „delete“, wenn Sie die Tabelle behalten und alle Daten löschen möchten, verwenden Sie „truncate“.
11. Was ist der Unterschied zwischen UNION und UNION ALL?
- Wenn Sie UNION ALL verwenden, werden doppelte Datensatzzeilen nicht zusammengeführt
- Die Effizienz von UNION ist höher als die von UNION ALL
12. Was ist der Unterschied zwischen count(1), count(*) und count(Spaltenname )?
Ausführungseffekt:
- count(*) umfasst alle Spalten, was der Anzahl der Zeilen entspricht. Bei der Berechnung der Ergebnisse werden NULL-Spaltenwerte nicht ignoriert
- count(1) Enthält Ignorieren Für alle Spalten stellt 1 die Codezeile dar. Beim Zählen der Ergebnisse wird der Spaltenwert nicht ignoriert. Die Anzahl (Spaltenname) umfasst nur die Spalte mit dem Spaltennamen ignoriert (hier ist das Leer nicht nur eine leere Zeichenfolge oder 0, sondern stellt die Anzahl von Null dar), dh wenn ein bestimmter Feldwert NULL ist, werden keine Statistiken gezählt.
-
Ausführungsgeschwindigkeit: Wenn der Spaltenname der Primärschlüssel ist, ist count(Spaltenname) schneller als count(1)
- Der Spaltenname ist nicht der Primärschlüssel, count(1) ist es schneller als count(Spaltenname)
- Wenn die Tabelle mehrere Spalten und keinen Primärschlüssel hat, ist die Ausführungseffizienz von count(1) besser als count(*)
- Wenn ein Primärschlüssel vorhanden ist, ist die Ausführungseffizienz von select count (Primärschlüssel) ist optimal
- Wenn die Tabelle nur ein Feld hat, ist select count(*) optimal.
- 13. Wie ist die Ausführungsreihenfolge einer SQL-Abfrageanweisung?
- FROM
: Führen Sie ein kartesisches Produkt (kartesisches Produkt) für die linke Tabelle in der FROM-Klausel aus, um die virtuelle Tabelle VT1 zu generieren Es wird nach der virtuellen Tabelle VT1 gefiltert und nur die Zeilen, die die erfüllen, werden in die virtuelle Tabelle VT2 eingefügt Zeilen in der reservierten Tabelle werden als externe Zeilen zur virtuellen Tabelle VT2 hinzugefügt, was zur virtuellen Tabelle VT3 führt. Wenn die FROM-Klausel mehr als zwei Tabellen enthält, wiederholen Sie die Schritte 1) bis 3) für die durch die vorherige Verbindung generierte Ergebnistabelle VT3 und die nächste Tabelle, bis alle Tabellen verarbeitet sind
- WHERE
: Die rechte virtuelle Tabelle VT3 gilt WHERE Filterbedingungen und nur Datensätze, die mit übereinstimmen, werden in die virtuelle Tabelle VT4 eingefügt |ROLLUP: Führen Sie CUBE- oder ROLLUP-Operationen für Tabelle VT5 aus, um Tabelle VT6 zu generieren.
SELECT: Führen Sie den SELECT-Vorgang zum zweiten Mal aus, wählen Sie die angegebene Spalte aus und fügen Sie sie in die virtuelle Tabelle VT8 ein.
DISTINCT: Doppelte Daten entfernen und virtuelle Tabelle VT9 generieren BY: Sortieren Sie die Datensätze in der virtuellen Tabelle VT9 nach , um die virtuelle Tabelle VT10 zu generieren. 11)
LIMIT: Nehmen Sie die Datensätze der angegebenen Zeile heraus, generieren Sie die virtuelle Tabelle VT11 und geben Sie sie zurück der abfragende Benutzer Datenbankarchitektur14. Sprechen Sie über die grundlegende Architektur von MySQL?
-
Das Diagramm der logischen MySQL-Architektur ist hauptsächlich in drei Schichten unterteilt:
- Client: Der Dienst der obersten Ebene gibt es nicht nur bei MySQL. Die meisten netzwerkbasierten Client/Server-Tools oder -Dienste haben eine ähnliche Architektur. Wie Verbindungsverarbeitung, Autorisierungsauthentifizierung, Sicherheit usw.
- Serverschicht: Die meisten Kerndienstfunktionen von MySQL befinden sich in dieser Schicht, einschließlich Abfrageanalyse, Analyse, Optimierung, Caching und allen integrierten Funktionen (z. B. Datum, Uhrzeit, Mathematik und Verschlüsselungsfunktionen) über alle Speicher-Engines hinweg In dieser Schicht werden Funktionen implementiert: gespeicherte Prozeduren, Trigger, Ansichten usw.
- Speicher-Engine-Schicht: Die dritte Schicht enthält die Speicher-Engine. Die Speicher-Engine ist für das Speichern und Abrufen von Daten in MySQL verantwortlich. Die Serverschicht kommuniziert über APIs mit der Speicher-Engine. Diese Schnittstellen schirmen die Unterschiede zwischen verschiedenen Speicher-Engines ab und machen diese Unterschiede für den Abfrageprozess der oberen Ebene transparent.
15. Wie wird eine SQL-Abfrageanweisung in MySQL ausgeführt?
- Überprüfen Sie zunächst, ob die Anweisung
eine Berechtigung hat. Wenn keine Berechtigung vorliegt, wird direkt eine Fehlermeldung zurückgegeben. Wenn eine Berechtigung vorliegt, wird zuerst der Cache abgefragt (vor MySQL8.0-Version). . 是否有权限 ,如果没有权限,直接返回错误信息,如果有权限会先查询缓存 (MySQL8.0 版本以前)。
- 如果没有缓存,分析器进行
语法分析 ,提取 sql 语句中 select 等关键元素,然后判断 sql 语句是否有语法错误,比如关键词是否正确等等。
- 语法解析之后,MySQL的服务器会对查询的语句进行优化,确定执行的方案。
- 完成查询优化后,按照生成的执行计划
调用数据库引擎接口
Wenn kein Cache vorhanden ist, führt der Analysator eine Grammatikanalyse durch, extrahiert Schlüsselelemente wie „select“ in der SQL-Anweisung und bestimmt dann, ob die SQL-Anweisung Syntaxfehler aufweist, z. B. ob die Schlüsselwörter korrekt sind , usw.
Nach der Syntaxanalyse optimiert der MySQL-Server die Abfrageanweisung und bestimmt den Ausführungsplan.
Nach Abschluss der Abfrageoptimierung rufen Sie die Datenbank-Engine-Schnittstelle gemäß dem generierten Ausführungsplan auf und geben die Ausführungsergebnisse zurück.
Speicher-Engine
16. Was sind die gängigen Speicher-Engines für MySQL?
Die wichtigsten Speicher-Engines und -Funktionen sind wie folgt: |
|
| Funktion | MylSAM MEMORY
InnoDB |
|
| Speicherlimit | 256 TB
RAM | 64 TB |
| Transaktionen unterstützen | Nein
Ja |
| Volltextindex unterstützen | Ja | Nein
Ja |
| Baum unterstützen Ja | Ja |
unterstützt Hash-Index Nein |
|
Vor MySQL 5.5 war die Standardspeicher-Engine MylSAM und nach 5.5 wurde sie zu InnoDB.
Der von InnoDB unterstützte Hash-Index ist adaptiv und generiert automatisch einen Hash-Index für die Tabelle, basierend auf der Nutzung der Tabelle.
Ab MySQL 5.6 unterstützt InnoDB die Volltextindizierung.
17. Wie sollten Sie eine Speicher-Engine auswählen?
Sie können grob so wählen:
- In den meisten Fällen reicht die Verwendung der Standard-InnoDB aus. Wenn Sie Transaktionssicherheitsfunktionen (ACID-Kompatibilität) für Commit, Rollback und Wiederherstellung bereitstellen möchten und eine Parallelitätskontrolle benötigen, ist InnoDB die erste Wahl.
- Wenn die Datentabelle hauptsächlich zum Einfügen und Abfragen von Datensätzen verwendet wird, bietet die MyISAM-Engine eine höhere Verarbeitungseffizienz.
- Wenn die Daten nur vorübergehend gespeichert werden, die Datenmenge nicht groß ist und keine hohe Datensicherheit erforderlich ist, können Sie die Daten in der MEMORY-Engine im Speicher speichern. Diese Engine wird als temporäre Tabelle verwendet MySQL zum Speichern der Zwischenergebnisse der Abfrage.
Welche Engine verwendet werden soll, kann je nach Bedarf flexibel ausgewählt werden, da die Speicher-Engine auf Tabellen basiert, sodass mehrere Tabellen in einer Datenbank unterschiedliche Engines verwenden können, um unterschiedliche Leistungen und tatsächliche Anforderungen zu erfüllen. Durch die Verwendung der geeigneten Speicher-Engine wird die Leistung der gesamten Datenbank verbessert.
18.Was sind die Hauptunterschiede zwischen InnoDB und MylSAM?
PS: MySQL8.0 wird langsam populär. Wenn es sich nicht um ein Interview handelt, müssen Sie nicht viel über MylSAM wissen.
1. Speicherstruktur: Jeder MyISAM wird in drei Dateien auf der Festplatte gespeichert. Alle InnoDB-Tabellen werden in derselben Datendatei gespeichert (es können auch mehrere Dateien oder unabhängige Tabellenbereichsdateien sein). Die Größe der InnoDB-Tabelle ist nur durch die Größe der Betriebssystemdatei begrenzt, die im Allgemeinen 2 GB beträgt.
2. Transaktionsunterstützung: MyISAM bietet keine Transaktionsunterstützung und verfügt über Transaktionssicherheitsfunktionen wie Transaktions- (Commit), Rollback- (Rollback) und Crash-Recovery-Funktionen.
3 Minimale Sperrgranularität: MyISAM unterstützt nur Sperren auf Tabellenebene. Die gesamte Tabelle wird während Aktualisierungen gesperrt, wodurch andere Abfragen und Aktualisierungen blockiert werden. 4. Indextyp: Der Index von MyISAM ist ein Clustered-Index und die Datenstruktur ist ein B-Baum. Der Index von InnoDB ist ein Nicht-Clustered-Index und die Datenstruktur ist ein B+-Baum. 5. Primärschlüssel ist erforderlich : MyISAM lässt die Existenz von Tabellen ohne Index oder Primärschlüssel zu, wenn InnoDB keinen Primärschlüssel oder einen nicht leeren eindeutigen Index festlegt. generiert automatisch einen 6-Byte-Primärschlüssel ( (für den Benutzer unsichtbar), Die Daten sind Teil des Hauptindex und der zusätzliche Index speichert den Wert des Hauptindex. 6. Die spezifische Anzahl der Zeilen in der Tabelle: MyISAM speichert die Gesamtzahl der Zeilen in der Tabelle Wenn Sie „select count( )“ aus der Tabelle verwenden, wird die gesamte Tabelle durchlaufen, aber nach dem Hinzufügen der Wehr-Bedingung behandeln MyISAM und InnoDB dies auf die gleiche Weise. 7. Fremdschlüsselunterstützung: MyISAM unterstützt keine Fremdschlüssel; InnoDB unterstützt Fremdschlüssel. Protokolle19. Was sind die MySQL-Protokolldateien? Die Funktionen jeweils vorstellen?
Es gibt viele MySQL-Protokolldateien, darunter:
Fehlerprotokoll (Fehlerprotokoll): Die Fehlerprotokolldatei zeichnet die Start-, Ausführungs- und Herunterfahrprozesse von MySQL auf und kann dabei helfen, MySQL-Probleme zu lokalisieren.
- Langsames Abfrageprotokoll (langsames Abfrageprotokoll): Das langsame Abfrageprotokoll wird zum Aufzeichnen von Abfrageanweisungen verwendet, deren Ausführungszeit die durch die Variable long_query_time definierte Länge überschreitet. Mithilfe des langsamen Abfrageprotokolls können Sie herausfinden, welche Abfrageanweisungen eine geringe Ausführungseffizienz für die Optimierung aufweisen.
- Allgemeines Abfrageprotokoll (allgemeines Protokoll): Das allgemeine Abfrageprotokoll zeichnet alle für die MySQL-Datenbank angeforderten Informationen auf, unabhängig davon, ob die Anforderung korrekt ausgeführt wird.
- Binärprotokoll (Bin-Protokoll): Das Binärprotokoll zeichnet alle von der Datenbank ausgeführten DDL- und DML-Anweisungen auf (mit Ausnahme der Datenabfrageanweisungen „select“, „show“ usw.), wird in Form von Ereignissen aufgezeichnet und binär gespeichert Dateien.
- Es gibt auch zwei InnoDB-Speicher-Engine-spezifische Protokolldateien:
-
Redo-Protokoll (Redo-Protokoll): Redo-Protokolle sind von entscheidender Bedeutung, da sie Transaktionsprotokolle für die InnoDB-Speicher-Engine aufzeichnen.
-
Rollback-Protokoll (Rückgängig-Protokoll): Das Rollback-Protokoll ist ebenfalls ein von der InnoDB-Engine bereitgestelltes Protokoll. Wie der Name schon sagt, besteht die Funktion des Rollback-Protokolls darin, die Daten zurückzusetzen. Wenn eine Transaktion die Datenbank ändert, zeichnet die InnoDB-Engine nicht nur das Redo-Protokoll auf, sondern generiert auch das entsprechende Rückgängig-Protokoll. Wenn die Transaktion fehlschlägt oder ein Rollback aufgerufen wird, wird die Transaktion zurückgesetzt, die Informationen im Rückgängig-Protokoll Mit dieser Funktion können Sie die Daten so wiederherstellen, wie sie vor der Änderung aussahen.
20. Was ist der Unterschied zwischen Binlog und Redo-Log?
- bin log zeichnet alle Protokolldatensätze im Zusammenhang mit der Datenbank auf, einschließlich Protokollen von Speicher-Engines wie InnoDB und MyISAM, während Redo Log nur Protokolle der InnoDB-Speicher-Engine aufzeichnet.
- Der aufgezeichnete Inhalt ist unterschiedlich. Das Bin-Protokoll zeichnet den spezifischen Vorgangsinhalt einer Transaktion auf, dh das Protokoll ist ein logisches Protokoll. Das Redo-Log zeichnet die physischen Änderungen an jeder Seite (Page) auf.
- Die Schreibzeit ist unterschiedlich. Das Bin-Protokoll wird nur vor dem Festschreiben der Transaktion festgeschrieben, dh es wird nur einmal auf die Festplatte geschrieben. Während die Transaktion ausgeführt wird, werden ständig Redo-Fehler in das Redo-Log geschrieben.
- Die Schreibmethoden sind ebenfalls unterschiedlich. Beim Redo-Log handelt es sich um ein zyklisches Schreiben und Löschen, während beim Bin-Log das Schreiben angehängt wird und bereits geschriebene Dateien nicht überschrieben werden.
21. Verstehen Sie, wie man eine Update-Anweisung ausführt?
Die Ausführung der Update-Anweisung wird durch die Zusammenarbeit der Serverschicht und der Engine-Schicht abgeschlossen. Zusätzlich zum Schreiben der Daten in die Tabelle müssen auch die entsprechenden Protokolle aufgezeichnet werden.
Der Executor sucht zunächst nach der Engine, um die Zeilen-ID=2 zu erhalten. Die ID ist der Primärschlüssel, und die Speicher-Engine ruft die Daten ab und findet diese Zeile. Wenn sich die Datenseite, auf der sich die Zeile mit der ID=2 befindet, bereits im Speicher befindet, wird sie direkt an den Executor zurückgegeben. Andernfalls muss sie zuerst von der Festplatte in den Speicher gelesen und dann zurückgegeben werden.
Der Executor ruft die von der Engine bereitgestellten Zeilendaten ab, addiert 1 zu diesem Wert, zum Beispiel war er früher N, aber jetzt ist er N+1, ruft eine neue Datenzeile ab und ruft dann die Engine auf Schnittstelle zum Schreiben dieser neuen Datenzeile.
Die Engine aktualisiert diese neue Datenzeile im Speicher und zeichnet den Aktualisierungsvorgang im Redo-Log auf. Zu diesem Zeitpunkt befindet sich das Redo-Log im Vorbereitungszustand. Informieren Sie anschließend den Testamentsvollstrecker darüber, dass die Ausführung abgeschlossen ist und die Transaktion jederzeit eingereicht werden kann.
Der Executor generiert das Binlog dieses Vorgangs und schreibt das Binlog auf die Festplatte.
Der Executor ruft die Commit-Transaktionsschnittstelle der Engine auf, und die Engine ändert das gerade geschriebene Redo-Protokoll in den Commit-Status, und die Aktualisierung ist abgeschlossen.
Wie aus der obigen Abbildung ersichtlich ist, analysiert und führt MySQL beim Ausführen der Update-Anweisung die Anweisung in der Serviceschicht aus, extrahiert und speichert gleichzeitig Daten in der Engine-Schicht und schreibt das Binlog in die Service-Schicht und Redo-Protokoll wird in InnoDB geschrieben.
Darüber hinaus gibt es beim Schreiben des Redo-Logs zwei Phasen der Übermittlung: Eine davon ist das Schreiben des prepare -Status, bevor das Binlog geschrieben wird, und die andere ist das Commit, nachdem das Binlog geschrieben wurde .code> Statusschreiben. <code>prepare 状态的写入,二是binlog写入之后commit 状态的写入。
22.那为什么要两阶段提交呢?
为什么要两阶段提交呢?直接提交不行吗?
我们可以假设不采用两阶段提交的方式,而是采用“单阶段”进行提交,即要么先写入redo log,后写入binlog;要么先写入binlog,后写入redo log。这两种方式的提交都会导致原先数据库的状态和被恢复后的数据库的状态不一致。
先写入redo log,后写入binlog:
在写完redo log之后,数据此时具有crash-safe 能力,因此系统崩溃,数据会恢复成事务开始之前的状态。但是,若在redo log写完时候,binlog写入之前,系统发生了宕机。此时binlog没有对上面的更新语句进行保存,导致当使用binlog进行数据库的备份或者恢复时,就少了上述的更新语句。从而使得id=2 这一行的数据没有被更新。
先写入binlog,后写入redo log:
写完binlog之后,所有的语句都被保存,所以通过binlog复制或恢复出来的数据库中id=2这一行的数据会被更新为a=1。但是如果在redo log写入之前,系统崩溃,那么redo log中记录的这个事务会无效,导致实际数据库中id=2
22. Warum gibt es dann eine zweistufige Einreichung?
Warum zweistufige Einreichung? Können Sie es nicht einfach direkt einreichen? Wir können davon ausgehen, dass wir anstelle einer zweiphasigen Übermittlungsmethode eine „einphasige“ Übermittlung übernehmen, dh entweder zuerst das Redo-Protokoll schreiben und dann das Binlog schreiben; Die Übermittlung auf diese beiden Arten führt dazu, dass der Status der Originaldatenbank nicht mit dem Status der wiederhergestellten Datenbank übereinstimmt. 🎜Schreiben Sie zuerst das Redo-Protokoll und dann das Binlog: 🎜🎜🎜Nach dem Schreiben des Redo-Protokolls sind die Daten zu diesem Zeitpunkt absturzsicher , sodass das System abstürzt und die Daten wiederhergestellt werden Beginn der Transaktion vorheriger Zustand. Wenn das System jedoch abstürzt, wenn das Redo-Log abgeschlossen ist und bevor das Binlog geschrieben wird, stürzt das System ab. Zu diesem Zeitpunkt speichert binlog die obige Aktualisierungsanweisung nicht, was dazu führt, dass die obige Aktualisierungsanweisung fehlt, wenn binlog zum Sichern oder Wiederherstellen der Datenbank verwendet wird. Infolgedessen werden die Daten in der Zeile id=2 nicht aktualisiert. 🎜🎜🎜🎜🎜 Schreiben Sie zuerst in Binlog und dann in das Redo-Log: 🎜🎜🎜Nach dem Schreiben von Binlog werden alle Anweisungen gespeichert, sodass die Daten in der Zeile id=2 in der über Binlog kopierten oder wiederhergestellten Datenbank auf a=1 aktualisiert werden. Wenn das System jedoch abstürzt, bevor das Redo-Log geschrieben wird, ist die im Redo-Log aufgezeichnete Transaktion ungültig, was dazu führt, dass die Daten in der Zeile id=2 in der tatsächlichen Datenbank nicht aktualisiert werden. 🎜🎜🎜🎜🎜Einfach ausgedrückt können sowohl Redo-Log als auch Binlog verwendet werden, um den Commit-Status einer Transaktion darzustellen, und das zweiphasige Commit dient dazu, die beiden Zustände logisch konsistent zu halten. 🎜23.redo log怎么刷入磁盘的知道吗?
redo log的写入不是直接落到磁盘,而是在内存中设置了一片称之为redo log buffer 的连续内存空间,也就是redo 日志缓冲区 。
什么时候会刷入磁盘?
在如下的一些情况中,log buffer的数据会刷入磁盘:
log buffer 的大小是有限的,如果不停的往这个有限大小的 log buffer 里塞入日志,很快它就会被填满。如果当前写入 log buffer 的redo 日志量已经占满了 log buffer 总容量的大约一半左右,就需要把这些日志刷新到磁盘上。
在事务提交时,为了保证持久性,会把log buffer中的日志全部刷到磁盘。注意,这时候,除了本事务的,可能还会刷入其它事务的日志。
有一个后台线程,大约每秒都会刷新一次log buffer 中的redo log 到磁盘。
重做日志缓存、重做日志文件都是以块(block) 的方式进行保存的,称之为重做日志块(redo log block) ,块的大小是固定的512字节。我们的redo log它是固定大小的,可以看作是一个逻辑上的 log group,由一定数量的log block 组成。
它的写入方式是从头到尾开始写,写到末尾又回到开头循环写。
其中有两个标记位置:
write pos 是当前记录的位置,一边写一边后移,写到第3号文件末尾后就回到0号文件开头。checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到磁盘。
当write_pos 追上checkpoint 时,表示redo log日志已经写满。这时候就不能接着往里写数据了,需要执行checkpoint 规则腾出可写空间。
所谓的checkpoint规则,就是checkpoint触发后,将buffer中日志页都刷到磁盘。
SQL 优化
24.慢SQL如何定位呢?
慢SQL的监控主要通过两个途径:
-
慢查询日志:开启MySQL的慢查询日志,再通过一些工具比如mysqldumpslow去分析对应的慢查询日志,当然现在一般的云厂商都提供了可视化的平台。
-
服务监控:可以在业务的基建中加入对慢SQL的监控,常见的方案有字节码插桩、连接池扩展、ORM框架过程,对服务运行中的慢SQL进行监控和告警。
25.有哪些方式优化慢SQL?
慢SQL的优化,主要从两个方面考虑,SQL语句本身的优化,以及数据库设计的优化。
避免不必要的列
这个是老生常谈,但还是经常会出的情况,SQL查询的时候,应该只查询需要的列,而不要包含额外的列,像slect * 这种写法应该尽量避免。
分页优化
在数据量比较大,分页比较深的情况下,需要考虑分页的优化。
例如:
select * from table where type = 2 and level = 9 order by id asc limit 190289,10;
优化方案:
-
延迟关联
先通过where条件提取出主键,在将该表与原数据表关联,通过主键id提取数据行,而不是通过原来的二级索引提取数据行
例如:
select a.* from table a,
(select id from table where type = 2 and level = 9 order by id asc limit 190289,10 ) b
where a.id = b.id
-
书签方式
书签方式就是找到limit第一个参数对应的主键值,根据这个主键值再去过滤并limit
例如:
select * from table where id >
(select * from table where type = 2 and level = 9 order by id asc limit 190
索引优化
合理地设计和使用索引,是优化慢SQL的利器。
利用覆盖索引
InnoDB使用非主键索引查询数据时会回表,但是如果索引的叶节点中已经包含要查询的字段,那它没有必要再回表查询了,这就叫覆盖索引
例如对于如下查询:
select name from test where city='上海'
我们将被查询的字段建立到联合索引中,这样查询结果就可以直接从索引中获取
alter table test add index idx_city_name (city, name);
低版本避免使用or查询
在 MySQL 5.0 之前的版本要尽量避免使用 or 查询,可以使用 union 或者子查询来替代,因为早期的 MySQL 版本使用 or 查询可能会导致索引失效,高版本引入了索引合并,解决了这个问题。
避免使用 != 或者 操作符
SQL中,不等于操作符会导致查询引擎放弃查询索引,引起全表扫描,即使比较的字段上有索引
解决方法:通过把不等于操作符改成or,可以使用索引,避免全表扫描
例如,把column’aaa’,改成column>’aaa’ or column,就可以使用索引了
适当使用前缀索引
适当地使用前缀所云,可以降低索引的空间占用,提高索引的查询效率。
比如,邮箱的后缀都是固定的“@xxx.com ”,那么类似这种后面几位为固定值的字段就非常适合定义为前缀索引
alter table test add index index2(email(6));
PS:需要注意的是,前缀索引也存在缺点,MySQL无法利用前缀索引做order by和group by 操作,也无法作为覆盖索引
避免列上函数运算
要避免在列字段上进行算术运算或其他表达式运算,否则可能会导致存储引擎无法正确使用索引,从而影响了查询的效率
select * from test where id + 1 = 50;
select * from test where month(updateTime) = 7;
正确使用联合索引
使用联合索引的时候,注意最左匹配原则。
JOIN优化
优化子查询
尽量使用 Join 语句来替代子查询,因为子查询是嵌套查询,而嵌套查询会新创建一张临时表,而临时表的创建与销毁会占用一定的系统资源以及花费一定的时间,同时对于返回结果集比较大的子查询,其对查询性能的影响更大
小表驱动大表
关联查询的时候要拿小表去驱动大表,因为关联的时候,MySQL内部会遍历驱动表,再去连接被驱动表。
比如left join,左表就是驱动表,A表小于B表,建立连接的次数就少,查询速度就被加快了。
select name from A left join B ;
适当增加冗余字段
增加冗余字段可以减少大量的连表查询,因为多张表的连表查询性能很低,所有可以适当的增加冗余字段,以减少多张表的关联查询,这是以空间换时间的优化策略
避免使用JOIN关联太多的表
《阿里巴巴Java开发手册》规定不要join超过三张表,第一join太多降低查询的速度,第二join的buffer会占用更多的内存。
如果不可避免要join多张表,可以考虑使用数据异构的方式异构到ES中查询。
排序优化
利用索引扫描做排序
MySQL有两种方式生成有序结果:其一是对结果集进行排序的操作,其二是按照索引顺序扫描得出的结果自然是有序的
但是如果索引不能覆盖查询所需列,就不得不每扫描一条记录回表查询一次,这个读操作是随机IO,通常会比顺序全表扫描还慢
因此,在设计索引时,尽可能使用同一个索引既满足排序又用于查找行
例如:
--建立索引(date,staff_id,customer_id)
select staff_id, customer_id from test where date = '2010-01-01' order by staff_id,customer_id;
只有当索引的列顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向都一样时,才能够使用索引来对结果做排序
UNION优化
条件下推
MySQL处理union的策略是先创建临时表,然后将各个查询结果填充到临时表中最后再来做查询,很多优化策略在union查询中都会失效,因为它无法利用索引
最好手工将where、limit等子句下推到union的各个子查询中,以便优化器可以充分利用这些条件进行优化
此外,除非确实需要服务器去重,一定要使用union all,如果不加all关键字,MySQL会给临时表加上distinct选项,这会导致对整个临时表做唯一性检查,代价很高。
26.怎么看执行计划(explain),如何理解其中各个字段的含义?
explain是sql优化的利器,除了优化慢sql,平时的sql编写,也应该先explain,查看一下执行计划,看看是否还有优化的空间。
直接在 select 语句之前增加explain 关键字,就会返回执行计划的信息。
id Spalte: MySQL weist jeder Select-Anweisung einen eindeutigen ID-Wert zu.
select_type Spalte, Abfragetyp, klassifiziert nach Assoziation, Union, Unterabfrage usw. Gängige Abfragetypen sind SIMPLE, PRIMARY.
Tabelle Spalte: Gibt an, auf welche Tabelle eine Erklärungszeile zugreift.
-
Typ Spalte: Eine der wichtigsten Spalten. Stellt die Art der Zuordnung oder den Zugriffstyp dar, mit dem MySQL bestimmt, wie Zeilen in der Tabelle gefunden werden.
Leistung vom besten zum schlechtesten: system > system : Wenn die Tabelle nur eine Datensatzzeile enthält (Systemtabelle), ist die Datenmenge sehr gering, Festplatten-E/A ist oft nicht erforderlich und die Geschwindigkeit ist sehr hoch
-
const const : Zeigt an, dass die Abfrage den Primärschlüssel primary key oder den eindeutigen Index unique trifft oder der verbundene Teil eine Konstante ist (const ) value . Diese Art des Scannens ist äußerst effizient, liefert eine kleine Datenmenge und ist sehr schnell. system : 当表仅有一行记录时(系统表),数据量很少,往往不需要进行磁盘IO,速度非常快
-
const
const :表示查询时命中 primary key 主键或者 unique 唯一索引,或者被连接的部分是一个常量(const )值。这类扫描效率极高,返回数据量少,速度非常快。
-
eq_ref
eq_ref :查询时命中主键primary key 或者 unique key 索引, type 就是 eq_ref 。
-
ref_or_null
ref_or_null :这种连接类型类似于 ref,区别在于 MySQL 会额外搜索包含NULL 值的行。
-
index_merge
index_merge :使用了索引合并优化方法,查询使用了两个以上的索引。
-
unique_subquery
unique_subquery :替换下面的 IN 子查询,子查询返回不重复的集合。
-
index_subquery
index_subquery :区别于unique_subquery ,用于非唯一索引,可以返回重复值。
-
range
range :使用索引选择行,仅检索给定范围内的行。简单点说就是针对一个有索引的字段,给定范围检索数据。在where 语句中使用 bettween...and 、、<code>> 、、<code>in 等条件查询 type 都是 range 。
-
index
index :Index 与ALL 其实都是读全表,区别在于index 是遍历索引树读取,而ALL
- eq_ref
eq_ref : Drücken Sie während der Abfrage den Index des Primärschlüssels Primärschlüssel oder Eindeutiger Schlüssel , Typ ist eq_ref .
ref_or_null
-
ref_or_null : Dieser Join-Typ ähnelt ref, außer dass MySQL zusätzlich nach Zeilen sucht, die NULL -Werte enthalten. index_merge
-
index_merge : Die Methode zur Optimierung der Indexzusammenführung wird verwendet und die Abfrage verwendet mehr als zwei Indizes. unique_subquery
-
unique_subquery : Ersetzen Sie die folgende IN -Unterabfrage, und die Unterabfrage gibt einen eindeutigen Satz zurück. index_subquery
-
index_subquery : Im Gegensatz zu unique_subquery wird es für nicht eindeutige Indizes verwendet und kann doppelte Werte zurückgeben. range
-
range : Zeilen mithilfe des Index auswählen und nur Zeilen innerhalb des angegebenen Bereichs abrufen. Vereinfacht ausgedrückt geht es darum, Daten innerhalb eines bestimmten Bereichs für ein indiziertes Feld abzurufen. Verwenden Sie bettween...and , , <code>> , where -Anweisung =, in und andere bedingte Abfragen type sind alle range . index
-
index : Index und ALL lesen tatsächlich die gesamte Tabelle, der Unterschied ist index Es wird durch Durchlaufen des Indexbaums gelesen, während ALL von der Festplatte gelesen wird. ALLE
Unnötig zu sagen, vollständiger Tabellenscan. Spalte: Zeigt an, welche Indizes die Abfrage zum Suchen verwenden kann. Dies ist wichtiger, wenn Indizes zur Optimierung von SQL verwendet werden.
key Spalte: Diese Spalte zeigt, welchen Index MySQL tatsächlich verwendet, um den Zugriff auf die Tabelle zu optimieren, und wird häufig verwendet, um festzustellen, ob der Index ungültig ist.
key_len Spalte: Zeigt die Verwendung von MySQL an.
-
- ref
Spalte: Die Ref-Spalte zeigt den Wert, der der Indexspalte entspricht. Gängige Werte sind: const (Konstante), func, NULL, Feldname. -
-
rows Spalte: Dies ist auch ein wichtiges Feld. Basierend auf statistischen Informationen schätzt der MySQL-Abfrageoptimierer die Anzahl der Datenzeilen, die SQL scannen und lesen muss, um die Ergebnismenge zu finden Effizienz von SQL: Je weniger Zeilen, desto besser.
🎜🎜Extra🎜 Spalte: Zeigt zusätzliche Informationen an, die nicht in andere Spalten passen. Obwohl sie als „extra“ bezeichnet werden, gibt es auch einige wichtige Informationen: 🎜🎜🎜🎜🎜Index verwenden: Zeigt an, dass MySQL einen abdeckenden Index verwendet Tabellenrückseiten vermeiden🎜 🎜Verwenden wo: Gibt an, dass die Filterung durchgeführt wird, nachdem die Speicher-Engine abgerufen wurde 🎜🎜Verwenden temporär: Gibt an, dass beim Sortieren der Abfrageergebnisse eine temporäre Tabelle verwendet wird. 🎜🎜🎜Index🎜🎜Der Index hat im MySQL-Interview oberste Priorität und muss gründlich gewonnen werden. 🎜🎜27. Können Sie kurz die Klassifizierung von Indizes erläutern? 🎜🎜Klassifizieren Sie Indizes aus drei verschiedenen Dimensionen: 🎜🎜🎜🎜🎜Zum Beispiel aus Sicht der grundlegenden Verwendung: 🎜🎜🎜Primärschlüsselindex: Der InnoDB-Primärschlüssel ist der Standardindex, und Datenspalten dürfen nicht wiederholt oder NULL sein . Eine Tabelle kann nur einen Primärschlüssel haben. 🎜🎜Einzigartiger Index: Die Duplizierung von Datenspalten ist nicht zulässig, NULL-Werte sind zulässig und eine Tabelle ermöglicht die Erstellung eindeutiger Indizes durch mehrere Spalten. 🎜🎜Normaler Index: Basisindextyp, keine Eindeutigkeitsbeschränkungen, NULL-Werte zulässig. 🎜🎜Kombinierter Index: Mehrere Spaltenwerte bilden einen Index für die kombinierte Suche, was effizienter ist als das Zusammenführen von Indizes🎜🎜🎜28 Warum beschleunigt die Verwendung eines Index Abfragen? 🎜🎜Die herkömmliche Abfragemethode durchläuft die Tabelle der Reihe nach. Unabhängig davon, wie viele Daten abgefragt werden, muss MySQL die Tabellendaten von Anfang bis Ende durchlaufen. 🎜Nachdem wir den Index hinzugefügt haben, generiert MySQL im Allgemeinen eine Indexdatei über den BTREE-Algorithmus. Beim Abfragen der Datenbank finden wir die zu durchsuchende Indexdatei, suchen in den relativ kleinen Indexdaten und ordnen sie dann den entsprechenden Daten zu die Sucheffizienz erheblich verbessern.
Es ist das Gleiche, als würden wir im Inhaltsverzeichnis des Buches nach dem entsprechenden Inhalt suchen.
29. Welche Punkte sind bei der Indexerstellung zu beachten?
Obwohl der Index ein leistungsstarkes Tool zur SQL-Leistungsoptimierung ist, ist die Indexpflege auch mit Kosten verbunden. Daher sollten Sie beim Erstellen eines Indexes auch auf Folgendes achten:
-
Der Index sollte auf Feldern basieren, die häufig in Abfrageanwendungen verwendet werden Es wird für die Beurteilung und Reihenfolge verwendet. Erstellen Sie einen Index für das (Ein-)Feld der Sortierung und Verknüpfung.
-
Die Anzahl der Indizes sollte angemessen sein
Indizes müssen Platz beanspruchen und auch während Aktualisierungen beibehalten werden.
-
Erstellen Sie keine Indizes für Felder mit geringer Differenzierung, wie z. B. Geschlecht.
Bei Feldern mit zu geringer Streuung wird die Anzahl der gescannten Zeilen begrenzt.
-
Verwenden Sie keine häufig aktualisierten Werte als Primärschlüssel oder Indizes.
Die Verwaltung von Indexdateien kostet Geld und führt auch zu Seitenaufteilungen und längeren E/A-Zeiten.
-
Der kombinierte Index stellt die Werte mit hohem Hashing (hoher Unterscheidung) in den Vordergrund
Um das Prinzip der Übereinstimmung des Präfixes ganz links zu erfüllen
-
Erstellen Sie einen kombinierten Index, anstatt einen einzelnen Spaltenindex zu ändern.
Kombinierter Index ersetzt mehrere einspaltige Indizes (für einspaltige Indizes kann MySQL grundsätzlich nur einen Index verwenden, daher ist die Verwendung kombinierter Indizes besser geeignet, wenn häufig mehrere Bedingungsabfragen verwendet werden)
Für Felder, die vorhanden sind zu lang, verwenden Sie Präfixindizes. Wenn der Feldwert relativ lang ist, verbraucht die Indizierung viel Platz und die Suche ist sehr langsam. Wir können einen Index erstellen, indem wir den vorherigen Teil des Feldes abfangen, der als Präfixindex bezeichnet wird.
-
Es wird nicht empfohlen, ungeordnete Werte (wie ID-Karten, UUID) als Indizes zu verwenden.
Wenn der Primärschlüssel unsicher ist, führt dies zu einer häufigen Aufteilung der Blattknoten und einer Fragmentierung des Festplattenspeichers.
30. Welche Indizes gibt es? In welchem Fall schlägt es fehl?
- Die Abfragebedingung enthält oder, was zu einem Indexfehler führen kann.
- Wenn der Feldtyp eine Zeichenfolge ist, muss das Wo in Anführungszeichen gesetzt werden, andernfalls ist der Index aufgrund der impliziten Typkonvertierung ungültig. Wie Platzhalter einen Index verursachen können Versagen.
- Gemeinsamer Index: Die Bedingungsspalte bei der Abfrage ist nicht die erste Spalte im gemeinsamen Index und der Index wird ungültig.
- Die Verwendung der in MySQL integrierten Funktion für die Indexspalte führt dazu, dass der Index ungültig wird.
- Beim Ausführen von Operationen an indizierten Spalten (z. B. +, -, *, /) wird der Index ungültig.
- Bei Verwendung von (!= oder , nicht in) in einem Indexfeld kann es zu einem Indexfehler kommen.
- Die Verwendung von „ist null“ oder „ist nicht null“ in Indexfeldern kann zu Indexfehlern führen.
- Die Codierungsformate von Feldern, die mit Links-Join-Abfragen oder Rechts-Join-Abfragen verknüpft sind, sind unterschiedlich, was zu Indexfehlern führen kann.
- Der MySQL-Optimierer schätzt, dass die Verwendung eines vollständigen Tabellenscans schneller ist als die Verwendung eines Index, sodass der Index nicht verwendet wird.
- 31. Für welche Szenarien sind Indizes nicht geeignet?
Tabellen mit einer relativ kleinen Datenmenge sind nicht für die Indizierung geeignet
- Felder, die häufiger aktualisiert werden, sind nicht für die Indizierung geeignet
- Felder mit geringer Diskretion sind nicht für die Indizierung geeignet (z. B. Geschlecht)
- 32. Wird der Index länger aufgebaut? Je mehr, desto besser?
Natürlich nicht.
Der Index belegt Speicherplatz Der Index verbessert zwar die Abfrageeffizienz, verringert jedoch die Effizienz beim Aktualisieren der Tabelle- . Beispielsweise muss MySQL jedes Mal, wenn eine Tabelle hinzugefügt, gelöscht oder geändert wird, nicht nur die Daten speichern, sondern auch die entsprechende Indexdatei speichern oder aktualisieren.
33.Wissen Sie, welche Datenstruktur der MySQL-Index verwendet?
MySQLs Standardspeicher-Engine ist InnoDB, das einen B+-Baumstrukturindex verwendet.
B+-Baum: Nur Blattknoten speichern Daten und Nicht-Blattknoten speichern nur Schlüsselwerte. Blattknoten werden mithilfe bidirektionaler Zeiger verbunden, und die untersten Blattknoten bilden eine bidirektional geordnete verknüpfte Liste.
In diesem Bild gibt es zwei wichtige Punkte:
- Der äußerste Block, wir nennen ihn einen Plattenblock. Sie können sehen, dass jeder Plattenblock mehrere Datenelemente (in Rosa dargestellt) und Zeiger (in Gelb/Grau dargestellt) enthält. Die Wurzelknotenplatte enthält beispielsweise die Datenelemente 17 und 35 enthalten die Zeiger P1, P2 und P3. P1 repräsentiert Plattenblöcke mit weniger als 17, P2 repräsentiert Plattenblöcke zwischen 17 und 35 und P3 repräsentiert Plattenblöcke mit mehr als 35. Die tatsächlichen Daten liegen in den Blattknoten vor, nämlich 3, 4, 5 ..., 65. Nicht-Blattknoten speichern keine echten Daten, sondern nur Datenelemente, die die Suchrichtung bestimmen. Beispielsweise sind 17 und 35 tatsächlich nicht in der Datentabelle vorhanden.
- Die Blattknoten sind über bidirektionale Zeiger verbunden. Der unterste Blattknoten bildet eine bidirektional geordnete verknüpfte Liste, die bereichsabgefragt werden kann.
34. Wie viele Daten kann ein B+-Baum speichern?
Angenommen, das Indexfeld ist vom Typ Bigint und die Länge beträgt 8 Byte. Die Zeigergröße ist im InnoDB-Quellcode auf 6 Bytes festgelegt, also insgesamt 14 Bytes. Nicht-Blattknoten (eine Seite) können 16384/14 = 1170 solcher Einheiten (Schlüsselwerte + Zeiger) speichern, was bedeutet, dass es 1170 Zeiger gibt.
Wenn die Baumtiefe 2 beträgt, gibt es 1170^2 Blattknoten und die speicherbaren Daten sind 1170117016=21902400.
Bei der Suche nach Daten entspricht eine Seitensuche einem IO. Mit anderen Worten: Für eine Tabelle mit etwa 20 Millionen sind für die Datenabfrage bis zu drei Festplattenzugriffe erforderlich.
Daher beträgt die Tiefe des B+-Baums in InnoDB im Allgemeinen 1-3 Schichten, was zig Millionen Datenspeicher ausfüllen kann.
35. Warum einen B+-Baum anstelle eines gewöhnlichen Binärbaums verwenden?
Sie können dieses Problem aus mehreren Dimensionen betrachten: ob die Abfrage schnell genug ist, ob die Effizienz stabil ist, wie viele Daten gespeichert werden und wie viele Festplattensuchen durchgeführt werden.
Warum nicht gewöhnliche Binärbäume verwenden?
Gewöhnliche Binärbäume degenerieren. Wenn sie zu einer verknüpften Liste degenerieren, entspricht dies einem vollständigen Tabellenscan. Im Vergleich zu binären Suchbäumen weisen ausgeglichene Binärbäume eine stabilere Sucheffizienz und eine schnellere Gesamtsuchgeschwindigkeit auf.
Warum nicht den Binärbaum ausgleichen?
Beim Lesen von Daten werden diese von der Festplatte in den Speicher gelesen. Wenn eine Datenstruktur wie ein Baum als Index verwendet wird, müssen Sie bei jeder Datensuche einen Knoten von der Festplatte lesen, bei dem es sich um einen Festplattenblock handelt. Ein ausgeglichener Binärbaum speichert jedoch nur einen Schlüsselwert und Daten pro Knoten Wenn es sich um einen B+-Baum handelt, können mehr Knotendaten gespeichert werden, und die Höhe des Baums wird ebenfalls verringert, sodass die Anzahl der Lesevorgänge auf der Festplatte verringert wird und die Abfrageeffizienz schneller ist.
36. Warum B+-Baum anstelle von B-Baum verwenden?
B+ hat diese Vorteile im Vergleich zu B-Tree:
-
Es ist eine Variante von B-Tree. Es kann alle Probleme lösen, die B-Tree lösen kann.
Zwei Hauptprobleme werden durch B Tree gelöst: Jeder Knoten speichert mehr Schlüsselwörter; mehr Pfade.
-
Stärkere Datenbank- und Tabellenscanfunktionen.
Wenn wir einen vollständigen Tabellenscan für die Tabelle durchführen möchten, müssen wir nur Blattknoten durchlaufen ausreichen, ist es nicht erforderlich, den gesamten B+Baum zu durchlaufen, um alle Daten zu erhalten.
-
B+Tree verfügt über stärkere Lese- und Schreibfähigkeiten auf der Festplatte als B Tree und hat weniger E/A-Zeiten
Der Stammknoten und die Zweigknoten speichern keine Datenbereiche, sodass ein Knoten mehr Schlüsselwörter speichern und die Festplatte gleichzeitig laden kann Zeit Es gibt mehr Schlüsselwörter und weniger IO-Zeiten.
-
Stärkere Sortierfähigkeit
Da sich auf dem Blattknoten ein Zeiger auf den nächsten Datenbereich befindet, bilden die Daten eine verknüpfte Liste.
-
Die Effizienz ist stabiler
B+Tree erhält Daten immer an den Blattknoten, sodass die Anzahl der E/As stabil ist.
37. Was ist der Unterschied zwischen Hash-Index und B+-Baum-Index?
- B+-Baum kann Bereichsabfragen durchführen, Hash-Index nicht.
- B+-Baum unterstützt das Prinzip des gemeinsamen Index ganz links, der Hash-Index unterstützt es jedoch nicht.
- B+-Baum unterstützt die Reihenfolge durch Sortieren, der Hash-Index unterstützt dies jedoch nicht.
- Der Hash-Index ist bei entsprechenden Abfragen effizienter als der B+-Baum.
- Wenn der B+-Baum Like für Fuzzy-Abfragen verwendet, können die Wörter nach Like (z. B. beginnend mit %) eine Optimierungsrolle spielen und der Hash-Index kann überhaupt keine Fuzzy-Abfrage durchführen.
38. Was ist der Unterschied zwischen Clustered-Index und Nicht-Clustered-Index?
Verstehen Sie zunächst, dass der Clustered-Index kein neuer Index, sondern eine Datenspeichermethode ist. Clustering bedeutet, dass Datenzeilen und benachbarte Schlüsselwerte kompakt zusammen gespeichert werden. Die beiden uns bekannten Speicher-Engines MyISAM verwenden nicht gruppierte Indizes und InnoDB verwendet gruppierte Indizes.
Man kann es so sagen:
- Die Datenstruktur des Index ist ein Baum. Der Index und die Daten des Clustered-Index sind die Daten des nicht gruppierten Indexes befinden sich nicht im selben Baum.
- 一个表中只能拥有一个聚簇索引,而非聚簇索引一个表可以存在多个。
- 聚簇索引,索引中键值的逻辑顺序决定了表中相应行的物理顺序;索引,索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同。
- 聚簇索引:物理存储按照索引排序;非聚集索引:物理存储不按照索引排序;
39.回表了解吗?
在InnoDB存储引擎里,利用辅助索引查询,先通过辅助索引找到主键索引的键值,再通过主键值查出主键索引里面没有符合要求的数据,它比基于主键索引的查询多扫描了一棵索引树,这个过程就叫回表。
例如:select * from user where name = ‘张三’;
40.覆盖索引了解吗?
在辅助索引里面,不管是单列索引还是联合索引,如果 select 的数据列只用辅助索引中就能够取得,不用去查主键索引,这时候使用的索引就叫做覆盖索引,避免了回表。
比如,select name from user where name = ‘张三’;
41.什么是最左前缀原则/最左匹配原则?
注意:最左前缀原则、最左匹配原则、最左前缀匹配原则这三个都是一个概念。
最左匹配原则:在InnoDB的联合索引中,查询的时候只有匹配了前一个/左边的值之后,才能匹配下一个。
根据最左匹配原则,我们创建了一个组合索引,如 (a1,a2,a3),相当于创建了(a1)、(a1,a2)和 (a1,a2,a3) 三个索引。
为什么不从最左开始查,就无法匹配呢?
比如有一个user表,我们给 name 和 age 建立了一个组合索引。
ALTER TABLE user add INDEX comidx_name_phone (name,age);
组合索引在 B+Tree 中是复合的数据结构,它是按照从左到右的顺序来建立搜索树的 (name 在左边,age 在右边)。
从这张图可以看出来,name 是有序的,age 是无序的。当 name 相等的时候, age 才是有序的。
这个时候我们使用where name= ‘张三‘ and age = ‘20 ‘ 去查询数据的时候, B+Tree 会优先比较 name 来确定下一步应该搜索的方向,往左还是往右。如果 name 相同的时候再比较age。但是如果查询条件没有 name,就不知道下一步应该查哪个 节点,因为建立搜索树的时候 name 是第一个比较因子,所以就没用上索引。
42.什么是索引下推优化?
索引条件下推优化(Index Condition Pushdown (ICP) ) 是MySQL5.6添加的,用于优化数据查询。
- 不使用索引条件下推优化时存储引擎通过索引检索到数据,然后返回给MySQL Server,MySQL Server进行过滤条件的判断。
- 当使用索引条件下推优化时,如果存在某些被索引的列的判断条件时,MySQL Server将这一部分判断条件下推给存储引擎,然后由存储引擎通过判断索引是否符合MySQL Server传递的条件,只有当索引符合条件时才会将数据检索出来返回给MySQL服务器。
例如一张表,建了一个联合索引(name, age),查询语句:select * from t_user where name like '张%' and age=10; ,由于name 使用了范围查询,根据最左匹配原则:
不使用ICP,引擎层查找到name like '张%' 的数据,再由Server层去过滤age=10 这个条件,这样一来,就回表了两次,浪费了联合索引的另外一个字段age 。
但是,使用了索引下推优化,把where的条件放到了引擎层执行,直接根据name like '张%' and age=10 的条件进行过滤,减少了回表的次数。
索引条件下推优化可以减少存储引擎查询基础表的次数,也可以减少MySQL服务器从存储引擎接收数据的次数。
锁
43.MySQL中有哪几种锁,列举一下?
如果按锁粒度划分,有以下3种:
- Tabellensperre: geringer Overhead, schnelle Sperre; hohe Sperrfestigkeit, hohe Wahrscheinlichkeit eines Sperrkonflikts, geringste Parallelität;
- Zeilensperre: Hoher Overhead, langsame Sperre; geringe Sperrgranularität, geringe Wahrscheinlichkeit eines Sperrenkonflikts und hohe Parallelität.
- Seitensperre: Der Overhead und die Sperrgeschwindigkeit liegen zwischen Tabellensperre und Zeilensperre. Die Sperrgranularität liegt zwischen Tabellensperre und Zeilensperre und die Parallelität ist durchschnittlich ,
Die gemeinsame Sperre (S-Sperre), auch Lesesperre (Lesesperre) genannt, blockiert sich nicht gegenseitig.
Exklusive Sperre (X-Sperre), auch Schreibsperre (Schreibsperre) genannt. Die exklusive Sperre blockiert innerhalb eines bestimmten Zeitraums nur eine Anforderung und verhindert, dass andere Sperren die geschriebenen Daten lesen. -
- 44. Sprechen Sie über die Implementierung von Zeilensperren in InnoDB?
Wir verwenden eine solche Benutzertabelle, um Sperren auf Zeilenebene darzustellen, in die 4 Datenzeilen eingefügt werden und die Primärschlüsselwerte 1, 6 sind. 8 und 12. Jetzt vereinfachen Die Clustered-Index-Struktur behält nur Datensätze bei.
Die Hauptimplementierung der Zeilensperre von InnoDB lautet wie folgt:
Datensatzsperre Datensatzsperre -
Datensatzsperre dient zum direkten Sperren eines Zeilendatensatzes. Wenn wir eindeutige Indizes (einschließlich eindeutiger Indizes und Clustered-Indizes) verwenden, um gleichwertige Abfragen durchzuführen und einen Datensatz genau abzugleichen, wird der Datensatz direkt gesperrt. Beispielsweise sperrt
select * from t where id=6 for update; den Datensatz von id=6 .
select * from t where id =6 for update; 就会将id=6 的记录锁定。
间隙锁(Gap Locks) 的间隙指的是两个记录之间逻辑上尚未填入数据的部分,是一个左开右开空间。
间隙锁就是锁定某些间隙区间的。当我们使用用等值查询或者范围查询,并且没有命中任何一个record ,此时就会将对应的间隙区间锁定。例如select * from t where id =3 for update; 或者select * from t where id > 1 and id 就会将(1,6)区间锁定。
临键指的是间隙加上它右边的记录组成的左开右闭区间。比如上述的(1,6]、(6,8]等。
临键锁就是记录锁(Record Locks)和间隙锁(Gap Locks)的结合,即除了锁住记录本身,还要再锁住索引之间的间隙。当我们使用范围查询,并且命中了部分record 记录,此时锁住的就是临键区间。注意,临键锁锁住的区间会包含最后一个record的右边的临键区间。例如select * from t where id > 5 and id 会锁住(4,7]、(7,+∞)。mysql默认行锁类型就是<code>临键锁(Next-Key Locks) 。当使用唯一性索引,等值查询匹配到一条记录的时候,临键锁(Next-Key Locks)会退化成记录锁;没有匹配到任何记录的时候,退化成间隙锁。
间隙锁(Gap Locks) 和临键锁(Next-Key Locks) 都是用来解决幻读问题的,在已提交读(READ COMMITTED) 隔离级别下,间隙锁(Gap Locks) 和临键锁(Next-Key Locks) Gap Lock Gap Lock
- Die Lücke in Gap Locks bezieht sich auf den logischen Teil zwischen zwei Datensätzen, der nicht mit Daten gefüllt wurde. Es handelt sich um einen links-offenen und rechts-offenen Raum.
Lücke Die Sperre dient dazu, bestimmte Lückenintervalle zu sperren. Wenn wir eine Gleichheitsabfrage oder eine Bereichsabfrage verwenden und keinen Datensatz treffen, wird das entsprechende Lückenintervall gesperrt. Beispiel: select * from t where id =3 for update; select * from t where id > will changes (1 , 6) Intervallsperre.
Next-Key-Sperre
Next-Key bezieht sich auf das linke offene und rechte geschlossene Intervall, bestehend aus der Lücke und dem Datensatz rechts davon. Zum Beispiel die oben genannten (1,6], (6,8] usw. 🎜🎜🎜Pro-Key-Sperren sind eine Kombination aus Datensatzsperren (Record Locks) und Lückensperren (Gap Locks), also zusätzlich zum Sperren des Datensatzes selbst Wenn wir eine Bereichsabfrage verwenden und auf einen Teil des record -Datensatzes zugreifen, wird das temporäre Schlüsselintervall gesperrt. Beachten Sie, dass das durch die temporäre Tastensperre gesperrte Intervall eingeschlossen ist Die rechte Seite des letzten Datensatzes. Zum Beispiel wird select * from t where id > 5 and id (4,7], (7, +∞). Wenn der Datensatz übereinstimmt, degeneriert er in Lückensperren 🎜<blockquote>🎜<code>Gap Locks und Next-Key Locks werden beide verwendet, um das Phantom-Leseproblem unter dem READ COMMITTED Isolationsstufe, Gap Locks und Next-Key Locks) sind ungültig 🎜🎜🎜Die oben genannten sind die drei Implementierungsalgorithmen von Zeilensperren. Darüber hinaus gibt es auch Einfügeabsichtssperren für die Zeilen Der Vorgang muss warten, bis die Transaktion, die die Lückensperre hält, festgeschrieben wird. Während des Wartens muss jedoch auch eine Sperrstruktur generiert werden, die angibt, dass eine Transaktion einen neuen Datensatz in eine bestimmte Lücke einfügen möchte Diese Art von Sperre wird jetzt als „Intention Locks“ bezeichnet. Die T1-Transaktion fügt dem Intervall (1,6) eine Intentionssperre hinzu Ein Datenelement mit der ID 4. Es wird eine Einfügungsabsichtssperre für das Intervall (1,6) erworben, und es gibt eine weitere T3-Transaktion, die ein Datenelement mit der ID 3 einfügen möchte. Es wird auch eine Einfügungsabsicht erworben Sperre im (1,6)-Bereich. Die beiden Einfügeabsichtssperren schließen sich jedoch nicht gegenseitig aus. 🎜🎜🎜🎜🎜45. Weißt du, was Absichtssperre ist? 🎜🎜Die Absichtssperre ist eine Sperre auf Tabellenebene, nicht zu verwechseln mit der Einfügeabsichtssperre. 🎜🎜Absichtssperren scheinen die Multigranularitätssperren von InnoDB zu unterstützen. Sie lösen das Problem der Koexistenz von Tabellensperren und Zeilensperren. 🎜Wenn wir einer Tabelle eine Tabellensperre hinzufügen müssen, müssen wir beurteilen, ob Datenzeilen in der Tabelle gesperrt sind, um festzustellen, ob das Hinzufügen erfolgreich sein kann.
Wenn keine Absichtssperre vorhanden ist, müssen wir alle Datenzeilen in der Tabelle durchlaufen, um festzustellen, ob eine Zeilensperre vorhanden ist.
Mit der Absichtssperre, einer Sperre auf Tabellenebene, können wir dies einmal direkt beurteilen ob Datenzeilen in der Tabelle gesperrt sind.
Mit der Absichtssperre beantragt die Datenbank automatisch eine absichtliche exklusive Sperre für die Tabelle für Transaktion A, bevor die auszuführende Transaktion A eine Zeilensperre (Schreibsperre) beantragt. Wenn Transaktion B eine Mutex-Sperre für die Tabelle beantragt, schlägt sie fehl, da eine absichtliche exklusive Sperre für die Tabelle vorliegt, und Transaktion B wird blockiert, wenn sie die Mutex-Sperre für die Tabelle beantragt.
46. Verstehen Sie MySQLs optimistisches Sperren und pessimistisches Sperren?
-
Pessimistische Parallelitätskontrolle:
Pessimistische Sperre geht davon aus, dass die durch sie geschützten Daten äußerst unsicher sind und jederzeit geändert werden können. Nachdem eine Transaktion die pessimistische Sperre erhalten hat, können andere Transaktionen die Daten nicht ändern Warten Sie vor der Ausführung, bis die Sperre aufgehoben wird.
Zeilensperren, Tabellensperren, Lesesperren und Schreibsperren in der Datenbank sind alles pessimistische Sperren.
- Optimistische Parallelitätskontrolle
Optimistische Sperre geht davon aus, dass sich die Daten nicht zu häufig ändern.
Optimistisches Sperren wird normalerweise durch Hinzufügen einer Version (Version) oder eines Zeitstempels (Zeitstempel) zur Tabelle implementiert, wobei die Version am häufigsten verwendet wird.
Wenn eine Transaktion Daten aus der Datenbank abruft, wird auch die Version der Daten (v1) entnommen. Wenn die Transaktion die Änderungen an den Daten abschließt und diese in der Tabelle aktualisieren möchte, wird die Version v1 entnommen Im Vergleich zur neuesten Version v2 bedeutet dies, dass während des Datenänderungszeitraums keine anderen Transaktionen die Daten in der Tabelle ändern dürfen Die Version wird während der Änderung um 1 erhöht. Dies zeigt an, dass die Daten geändert wurden.
Wenn v1 nicht gleich v2 ist, bedeutet dies, dass die Daten während des Datenänderungszeitraums geändert wurden. Zu diesem Zeitpunkt dürfen die Daten nicht in der Tabelle aktualisiert werden. Die allgemeine Lösung besteht darin, den Benutzer zu benachrichtigen und lassen Sie sie wieder operieren. Im Gegensatz zum pessimistischen Sperren wird das optimistische Sperren normalerweise von Entwicklern implementiert.
47.Haben Sie jemals ein Deadlock-Problem in MySQL festgestellt?
Die allgemeinen Schritte zur Fehlerbehebung bei Deadlocks sind wie folgt:
(1) Überprüfen Sie das Deadlock-Protokoll und zeigen Sie den Innodb-Status der Engine an.
(2) Finden Sie den Deadlock-SQL heraus.
(3) Analysieren Sie die SQL-Sperrsituation ) Simulieren Sie einen Deadlock-Fall
(5) Analysieren Sie das Deadlock-Protokoll
(6) Analysieren Sie das Deadlock-Ergebnis
Natürlich ist dies nur eine einfache Prozessbeschreibung. Tatsächlich sind Deadlocks in der Produktion alle möglichen seltsamen Dinge Es ist schwierig, sie zu beheben und zu beheben.
Transaktionen
48. Was sind die vier Hauptmerkmale von MySQL-Transaktionen?
Atomizität: Die Transaktion wird als Ganzes ausgeführt, und entweder werden alle darin enthaltenen Vorgänge für die Datenbank ausgeführt oder es werden keine ausgeführt.
- Konsistenz: bedeutet, dass die Daten nicht vor Beginn der Transaktion und nach Ende der Transaktion zerstört werden. Wenn Konto A 10 Yuan auf Konto B überweist, bleibt der Gesamtbetrag von A und B unabhängig von Erfolg oder Misserfolg unverändert.
- Isolation: Wenn mehrere Transaktionen gleichzeitig zugreifen, sind die Transaktionen voneinander isoliert, das heißt, eine Transaktion hat keinen Einfluss auf die laufenden Auswirkungen anderer Transaktionen. Kurz gesagt bedeutet dies, dass es keinen Konflikt zwischen Angelegenheiten gibt.
- Persistenz: Gibt an, dass nach Abschluss der Transaktion die durch die Transaktion an der Datenbank vorgenommenen betrieblichen Änderungen dauerhaft in der Datenbank gespeichert werden.
- 49. Auf welche Garantie verlässt sich ACID?
Die Isolierung- von Transaktionen wird durch den Datenbanksperrmechanismus erreicht. Die
Konsistenz- der Transaktion wird durch das Rückgängig-Protokoll garantiert: Das Rückgängig-Protokoll ist ein logisches Protokoll, das die Einfüge-, Aktualisierungs- und Löschvorgänge der Transaktion aufzeichnet. Während des Rollbacks erfolgen die umgekehrten Lösch-, Aktualisierungs- und Einfügevorgänge durchgeführt, um die Daten wiederherzustellen. Die
Atomarität- und Dauerhaftigkeit der Transaktion werden durch das Redo-Log garantiert: Das Redo-Log wird als Redo-Log bezeichnet. Bei der Übermittlung einer Transaktion müssen alle Protokolle der Transaktion zunächst in das Redo-Log geschrieben werden aus Gründen der Persistenz wird die Transaktion erst mit dem Commit-Vorgang abgeschlossen.
50. Was sind die Isolationsstufen von Transaktionen? Was ist die Standardisolationsstufe von MySQL?
Read Uncommitted
- Read Committed
- Repeatable Read
- Serializable
- MySQLs Standardtransaktionsisolationsstufe ist Repeatable Read.
51.Was sind Phantom Reads, Dirty Reads und nicht wiederholbare Reads?
- Transaktionen A und B werden abwechselnd ausgeführt, und Transaktion A liest die nicht festgeschriebenen Daten von Transaktion B. Dies ist Dirty Reading.
- Innerhalb eines Transaktionsbereichs lesen zwei identische Abfragen denselben Datensatz, geben jedoch unterschiedliche Daten zurück. Dies ist ein nicht wiederholbares Lesen.
- Transaktion A fragt die Ergebnismenge eines Bereichs ab, und eine andere gleichzeitige Transaktion B fügt Daten in diesen Bereich ein bzw. löscht sie und schreibt sie stillschweigend fest. Dann fragt Transaktion A denselben Bereich erneut ab, und die durch die beiden Lesevorgänge erhaltene Ergebnismenge ist unterschiedlich. Es ist dasselbe, das ist Phantomlesung.
Unterschiedliche Isolationsstufen, Probleme, die bei gleichzeitigen Transaktionen auftreten können:
Isolationsstufe |
Dirty Read |
Nicht wiederholbares Lesen |
Phantom Read |
Lesen. Nicht festgeschrieben Ja |
ist |
|
Serialisierbar Serialisierbar |
Nein
Nein |
Nein |
|
52. Wie werden die verschiedenen Isolationsstufen von Transaktionen implementiert?
Ungebunden lesen
Ungebunden lesen, natürlich wird das Prinzip des Lesens ohne Sperren übernommen.
- Transaktionales Lesen sperrt nicht und blockiert nicht das Lesen und Schreiben anderer Transaktionen.
- Transaktionales Schreiben blockiert nicht das Lesen anderer Transaktionen.
Lesen ist festgeschrieben und wiederholbar lesen
Lesen Die festgeschriebenen und wiederholbaren Leseebenen nutzen ReadView und MVCC , das heißt, jede Transaktion kann nur die Version lesen, die sie sehen kann (ReadView). ReadView 和MVCC ,也就是每个事务只能读取它能看到的版本(ReadView)。
- READ COMMITTED:每次读取数据前都生成一个ReadView
- REPEATABLE READ : 在第一次读取数据时生成一个ReadView
串行化
串行化的实现采用的是读写都加锁的原理。
串行化的情况下,对于同一行事务,写 会加写锁 ,读 会加读锁 。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。
53.MVCC了解吗?怎么实现的?
MVCC(Multi Version Concurrency Control),中文名是多版本并发控制,简单来说就是通过维护数据历史版本,从而解决并发访问情况下的读一致性问题。关于它的实现,要抓住几个关键点,隐式字段、undo日志、版本链、快照读&当前读、Read View。
版本链
对于InnoDB存储引擎,每一行记录都有两个隐藏列DB_TRX_ID、DB_ROLL_PTR
-
DB_TRX_ID ,事务ID,每次修改时,都会把该事务ID复制给DB_TRX_ID ;
-
DB_ROLL_PTR ,回滚指针,指向回滚段的undo日志。
假如有一张user 表,表中只有一行记录,当时插入的事务id为80。此时,该条记录的示例图如下:
接下来有两个DB_TRX_ID 分别为100 、200 的事务对这条记录进行update 操作,整个过程如下:
由于每次变动都会先把undo 日志记录下来,并用DB_ROLL_PTR 指向undo 日志地址。因此可以认为,对该条记录的修改日志串联起来就形成了一个版本链 ,版本链的头节点就是当前记录最新的值。如下:
ReadView
对于Read Committed 和Repeatable Read 隔离级别来说,都需要读取已经提交的事务所修改的记录,也就是说如果版本链中某个版本的修改没有提交,那么该版本的记录时不能被读取的。所以需要确定在Read Committed 和Repeatable Read 隔离级别下,版本链中哪个版本是能被当前事务读取的。于是就引入了ReadView READ COMMITTED: Vor jedem Datenlesen eine ReadView generierenREPEATABLE READ: Beim erstmaligen Lesen von Daten eine ReadView generieren
Serialisierung
- Die Serialisierung wird nach dem Prinzip der Sperrung von Lesen und Schreiben implementiert.
- Im Fall der Serialisierung fügt
write für dieselbe Transaktionszeile eine Schreibsperre hinzu und read fügt einen Lesesperre. Wenn ein Lese-/Schreibsperrenkonflikt auftritt, muss die Transaktion, auf die später zugegriffen wird, auf den Abschluss der vorherigen Transaktion warten, bevor sie weiter ausgeführt werden kann.
53.Verstehen Sie MVCC? Wie wird es erreicht?
- MVCC (Multi Version Concurrency Control), der chinesische Name ist Multi-Version-Parallelitätskontrolle. Einfach ausgedrückt, löst es das Lesekonsistenzproblem beim gleichzeitigen Zugriff durch die Beibehaltung historischer Datenversionen. In Bezug auf die Implementierung müssen wir mehrere wichtige Punkte verstehen:
- Implizite Felder, Rückgängig-Protokolle, Versionsketten, Snapshot-Lesen und aktuelles Lesen sowie Leseansicht
.
Versionskette🎜🎜🎜Für die InnoDB-Speicher-Engine hat jede Datensatzzeile zwei versteckte Spalten🎜DB_TRX_ID, DB_ROLL_PTR🎜🎜🎜🎜DB_TRX_ID , Transaktions-ID, jedes Mal, wenn sie geändert wird, wird die Transaktions-ID wird nach DB_TRX_ID kopiert; 🎜🎜DB_ROLL_PTR , der Rollback-Zeiger zeigt auf das Rückgängig-Protokoll des Rollback-Segments. 🎜🎜🎜🎜🎜 Angenommen, es gibt eine user -Tabelle mit nur einer Datensatzzeile und die zu diesem Zeitpunkt eingefügte Transaktions-ID ist 80. Derzeit sieht das Beispielbild dieses Datensatzes wie folgt aus: 🎜🎜🎜🎜Als nächstes müssen zwei Transaktionen ausgeführt werden, wobei DB_TRX_ID 100 und 200 ist Bei diesem Datensatzcode>Update-Vorgang ist der gesamte Vorgang wie folgt: 🎜🎜🎜🎜Da jede Änderung zuerst im Rückgängig -Protokoll aufgezeichnet wird, verwenden Sie DB_ROLL_PTR , um darauf zu verweisen rückgängig machen Protokolladresse. Daher kann davon ausgegangen werden, dass 🎜die Änderungsprotokolle dieses Datensatzes zu einer Versionskette verkettet werden und der Kopfknoten der Versionskette der neueste Wert des aktuellen Datensatzes ist🎜. Wie folgt: 🎜🎜 🎜 🎜🎜ReadView🎜🎜🎜Für die Isolationsstufen Read Committed und Repeatable Read ist es notwendig, die durch die übermittelte Transaktion geänderten Datensätze zu lesen Das heißt, wenn die Änderungen einer bestimmten Version in der Versionskette nicht festgeschrieben werden, können die Datensätze dieser Version nicht gelesen werden. Daher muss ermittelt werden, welche Version in der Versionskette von der aktuellen Transaktion unter den Isolationsstufen Read Committed und Repeatable Read gelesen werden kann. Daher wurde das Konzept von ReadView eingeführt, um dieses Problem zu lösen. 🎜🎜🎜Read View ist die Leseansicht, die beim Ausführen einer Transaktion generiert wird 🎜Snapshot Read🎜, was einem in einem bestimmten Zeitplan aufgezeichneten Snapshot entspricht. Durch diesen Snapshot können wir Folgendes erhalten: 🎜🎜🎜🎜🎜🎜m_ids: gibt an, wann Die ReadView wird generiert. Liste der Transaktions-IDs aktiver Lese- und Schreibtransaktionen im aktuellen System. 🎜🎜min_trx_id: Gibt die kleinste Transaktions-ID unter den aktiven Lese- und Schreibtransaktionen im aktuellen System an, wenn ReadView generiert wird, d. h. den kleinsten Wert in m_ids. 🎜🎜max_trx_id: Gibt den ID-Wert an, der der nächsten Transaktion im System beim Generieren von ReadView zugewiesen werden soll. 🎜🎜creator_trx_id: Gibt die Transaktions-ID der Transaktion an, die die ReadView generiert hat. Wenn Sie auf einen Datensatz zugreifen, müssen Sie nur die folgenden Schritte ausführen, um festzustellen, ob eine bestimmte Version des Datensatzes sichtbar ist: 🎜
- Wenn der Attributwert DB_TRX_ID der Version, auf die zugegriffen wird, mit dem Wert „creator_trx_id“ in ReadView übereinstimmt, bedeutet dies, dass die aktuelle Transaktion auf ihre eigenen geänderten Datensätze zugreift, sodass die aktuelle Transaktion auf diese Version zugreifen kann.
- Wenn der DB_TRX_ID-Attributwert der Version, auf die zugegriffen wird, kleiner ist als der min_trx_id-Wert in ReadView, bedeutet dies, dass die Transaktion, die diese Version generiert hat, festgeschrieben wurde, bevor die aktuelle Transaktion ReadView generiert, sodass die aktuelle Transaktion auf diese Version zugreifen kann.
- Wenn der Attributwert DB_TRX_ID der Version, auf die zugegriffen wird, größer ist als der Wert max_trx_id in ReadView, bedeutet dies, dass die Transaktion, die diese Version generiert hat, nach der Generierung von ReadView durch die aktuelle Transaktion gestartet wurde, sodass die aktuelle Transaktion nicht auf diese Version zugreifen kann.
- Wenn der DB_TRX_ID-Attributwert der aufgerufenen Version zwischen min_trx_id und max_trx_id von ReadView liegt, müssen Sie feststellen, ob der trx_id-Attributwert in der m_ids-Liste enthalten ist. Wenn dies der Fall ist, bedeutet dies, dass die Transaktion diese Version generiert hat Die ReadView-Version ist immer noch aktiv. Wenn nicht, bedeutet dies, dass die Transaktion, die diese Version generiert hat, festgeschrieben wurde und auf diese Version zugegriffen werden kann.
Wenn eine bestimmte Datenversion für die aktuelle Transaktion nicht sichtbar ist, folgen Sie der Versionskette, um die nächste Datenversion zu finden, führen Sie die oben genannten Schritte weiter aus, um die Sichtbarkeit zu ermitteln, und so weiter, bis zur letzten Version in die Versionskette. Wenn die letzte Version nicht sichtbar ist, bedeutet dies, dass der Datensatz für die Transaktion vollständig unsichtbar ist und das Abfrageergebnis den Datensatz nicht enthält.
In MySQL besteht ein sehr großer Unterschied zwischen den Isolationsstufen READ COMMITTED und REPEATABLE READ darin, dass sie ReadView zu unterschiedlichen Zeiten generieren.
READ COMMITTED ist das Generieren einer ReadView vor jedem Datenlesen, sodass Sie sicherstellen können, dass Sie die von anderen Transaktionen übermittelten Daten jedes Mal lesen können; REPEATABLE READ ist das Generieren einer ReadView, wenn Sie Daten zum ersten Mal lesen kann sicherstellen, dass die Ergebnisse nachfolgender Messungen vollständig konsistent sind.
Hohe Verfügbarkeit/Leistung
54. Verstehen Sie die Trennung von Datenbank-Lesen und -Schreiben?
Das Grundprinzip der Lese- und Schreibtrennung besteht darin, Datenbank-Lese- und Schreibvorgänge auf verschiedene Knoten zu verteilen. Das Folgende ist das grundlegende Architekturdiagramm:
Die grundlegende Implementierung der Lese- und Schreibtrennung ist:
- Die Datenbank Der Server baut einen Master-Slave-Cluster auf. Es können ein Master und ein Slave oder ein Master und mehrere Slaves verwendet werden.
- Der Datenbankhost ist für Lese- und Schreibvorgänge verantwortlich, und der Slave ist nur für Lesevorgänge verantwortlich.
- Der Datenbankhost synchronisiert Daten durch Replikation mit dem Slave-Computer und jeder Datenbankserver speichert alle Geschäftsdaten.
- Der Business-Server sendet Schreibvorgänge an den Datenbankhost und Lesevorgänge an den Datenbankslave.
55. Wie realisiert man die Zuordnung von Lese- und Schreibtrennung?
Um Lese- und Schreibvorgänge zu trennen und dann auf verschiedene Datenbankserver zuzugreifen, gibt es im Allgemeinen zwei Möglichkeiten: Programmcode-Kapselung und Middleware-Kapselung.
1. Programmcode-Kapselung
Programmcode-Kapselung bezieht sich auf die Abstraktion einer Datenzugriffsschicht im Code (einige Artikel nennen diese Methode daher auch „Mittelschicht-Kapselung“), um eine Trennung von Lese- und Schreibvorgängen und Datenbankserververbindungen zu erreichen Management. Beispielsweise kann eine einfache Kapselung auf Basis von Hibernate eine Lese-Schreib-Trennung erreichen:
Unter den aktuellen Open-Source-Implementierungslösungen ist Taobaos TDDL (Taobao Distributed Data Layer, Spitzname: Der Kopf ist zu groß) relativ berühmt.
2. Middleware-Kapselung
Middleware-Kapselung bezieht sich auf ein unabhängiges System, das die Trennung von Lese- und Schreibvorgängen und die Verwaltung von Datenbankserververbindungen realisiert. Die Middleware stellt dem Geschäftsserver ein SQL-kompatibles Protokoll zur Verfügung, und der Geschäftsserver muss das Lesen und Schreiben nicht selbst trennen.
Für den Business-Server gibt es keinen Unterschied zwischen dem Zugriff auf die Middleware und dem Zugriff auf die Datenbank. Aus Sicht des Business-Servers ist die Middleware tatsächlich ein Datenbankserver.
Die Grundstruktur ist:
56 Verstehen Sie das Prinzip der Master-Slave-Replikation?
- Master schreibt Daten und aktualisiert Binlog.
- Master erstellt einen Dump-Thread, um Binlog an den Slave zu übertragen Öffnen Sie einen SQL-Thread, um das Relay-Log-Ereignis zu lesen und auf dem Slave auszuführen, um die Synchronisierung abzuschließen. 57. Wie gehe ich mit der Master-Slave-Synchronisierungsverzögerung um?
- Der Grund für die Verzögerung der Master-Slave-Synchronisation
-
Ein Server öffnet N Links für die Verbindung von Clients, sodass große gleichzeitige Aktualisierungsvorgänge stattfinden. Es dauert jedoch nur einen Thread, um das Binlog vom Server zu lesen Es kann lange dauern oder weil eine bestimmte SQL die Tabelle sperren muss, was zu einem großen SQL-Rückstand auf dem Master-Server führt und nicht mit dem Slave-Server synchronisiert wird. Dies führt zu einer Master-Slave-Inkonsistenz, also einer Master-Slave-Verzögerung.
Lösungen für die Master-Slave-Synchronisierungsverzögerung
Es gibt mehrere gängige Methoden, um die Master-Slave-Replikationsverzögerung zu beheben:
Zum Beispiel wird das Registrierungskonto abgeschlossen. Schließlich wird auch der Lesevorgang zum Lesen des Kontos beim Anmelden an den Hauptdatenbankserver gesendet. Diese Methode ist stark an das Unternehmen gebunden und hat größere Eingriffe und Auswirkungen auf das Unternehmen. Wenn ein neuer Programmierer nicht weiß, wie man Code auf diese Weise schreibt, führt dies zu einem Fehler.
Das sekundäre Lesen ist nicht an das Unternehmen gebunden und muss nur die API kapseln, um auf die zugrunde liegende Datenbank zuzugreifen Der Nachteil besteht darin, dass bei vielen sekundären Lesevorgängen der Lesevorgangsdruck auf dem Host erheblich zunimmt. Wenn ein Hacker beispielsweise gewaltsam ein Konto knackt, führt dies zu einer großen Anzahl sekundärer Lesevorgänge. Der Host kann dem Druck der Lesevorgänge möglicherweise nicht standhalten und zusammenbrechen.
Wichtige Geschäftslese- und -schreibvorgänge verweisen alle auf den Host, und unkritische Geschäftsvorgänge verwenden Lese- und Schreibtrennung Der Host, die Einführung des Benutzers, Unternehmen wie Liebe und Ebene können die Lese-/Schreibtrennung verwenden, denn selbst wenn der Benutzer seine Selbsteinführung ändert, wird er bei der Abfrage feststellen, dass die Selbsteinführung immer noch dieselbe ist viel kleiner, als sich nicht anmelden zu können, und es ist tolerierbar. 58. Wie teilt man die Datenbank normalerweise auf?
Vertikale Datenbankaufteilung: Basierend auf Tabellen werden verschiedene Tabellen je nach Unternehmenseigentum in verschiedene Datenbanken aufgeteilt.
Horizontale Datenbankaufteilung: Basierend auf Feldern und nach bestimmten Strategien (Hash, Bereich usw.) werden die Daten in einer Datenbank in mehrere Datenbanken aufgeteilt.
59. Wie teilt man dann die Uhren auf? Horizontale Tabellenaufteilung: Teilen Sie die Daten in einer Tabelle basierend auf Feldern und nach bestimmten Strategien (Hash, Bereich usw.) in mehrere Tabellen auf. Vertikale Tabellenaufteilung: Basierend auf den Feldern und entsprechend der Aktivität der Felder werden die Felder in der Tabelle in verschiedene Tabellen (Haupttabelle und erweiterte Tabelle) aufgeteilt. 60 Welche Routing-Methoden gibt es für die horizontale Tabellenaufteilung? Was ist Routing? Das ist die Tabelle, in die die Daten aufgeteilt werden sollen.
Es gibt drei Hauptroutingmethoden für horizontales Tabellen-Sharding:
Range-Routing : Wählen Sie geordnete Datenspalten (z. B. Formung, Zeitstempel usw.) als Routing-Bedingungen aus, und verschiedene Segmente werden in verschiedene Datenbanktabellen verteilt. - Wir können einige Zahlungssysteme beobachten und feststellen, dass wir Zahlungsaufzeichnungen nur innerhalb eines Jahres überprüfen können. Dies kann daran liegen, dass das Zahlungsunternehmen die Tabellen nach Zeit aufgeteilt hat.
Die Komplexität des Bereichsrouting-Designs spiegelt sich hauptsächlich in der Auswahl der Segmentgröße wider. Wenn das Segment zu klein ist, führt dies zu zu vielen Untertabellen nach der Segmentierung und erhöht die Wartungskomplexität , es kann zu einer einzelnen Tabelle kommen. Es wird allgemein empfohlen, dass die Segmentgröße zwischen 1 Million und 20 Millionen liegt. Der Vorteil des Range-Routings besteht darin, dass neue Tabellen problemlos erweitert werden können, wenn die Datenmenge zunimmt. Wenn die aktuelle Anzahl der Benutzer beispielsweise 1 Million beträgt und die Anzahl auf 10 Millionen steigt, müssen Sie nur eine neue Tabelle hinzufügen und die ursprünglichen Daten müssen nicht geändert werden. Ein relativ impliziter Nachteil des Bereichsroutings ist die ungleichmäßige Verteilung. Wenn die Tabelle in 10 Millionen Teile unterteilt wird, ist es möglich, dass die tatsächliche Datenmenge, die in einem Segment gespeichert wird, nur 1.000 beträgt, während die tatsächliche Datenmenge, die in einem anderen Segment gespeichert wird, 900 beträgt . Zehntausend.
Hash-Routing : Wählen Sie den Wert einer bestimmten Spalte (oder einer Kombination bestimmter Spalten) für den Hash-Vorgang aus und verteilen Sie ihn dann basierend auf dem Hash-Ergebnis auf verschiedene Datenbanktabellen. - Nehmen wir auch die Bestell-ID als Beispiel: Wenn wir von Anfang an 4 Datenbanktabellen planen, kann der Routing-Algorithmus einfach den Wert von id % 4 verwenden, um die Datenbanktabellennummer darzustellen, zu der die Daten gehören 12 wird in die Zahl eingefügt. In der Untertabelle von 50 wird die Reihenfolge mit der ID 13 in die Worttabelle mit der Nummer 61 eingefügt.
Die Komplexität des Hash-Routing-Designs spiegelt sich hauptsächlich in der Auswahl der anfänglichen Anzahl von Tabellen wider. Zu viele Tabellen sind mühsam zu verwalten, und zu wenige Tabellen können zu Leistungsproblemen bei einer einzelnen Tabelle führen. Nach der Verwendung des Hash-Routings ist es sehr mühsam, die Anzahl der Untertabellen zu erhöhen, und alle Daten müssen neu verteilt werden. Die Vor- und Nachteile des Hash-Routings sind grundsätzlich entgegengesetzt zu denen des Range-Routings. Der Vorteil des Hash-Routings besteht darin, dass die Tabellen relativ gleichmäßig verteilt sind. Der Nachteil besteht darin, dass das Erweitern neuer Tabellen mühsam ist und alle Daten neu verteilt werden müssen.
-
Routing konfigurieren: Beim Konfigurieren des Routings handelt es sich um eine Routing-Tabelle, bei der eine unabhängige Tabelle zum Aufzeichnen von Routing-Informationen verwendet wird. Am Beispiel der Bestell-ID fügen wir eine neue order_router-Tabelle hinzu. Diese Tabelle enthält zwei Spalten: orderjd und tablejd. Die entsprechende table_id kann basierend auf orderjd abgefragt werden.
Die Routing-Konfiguration ist einfach im Design und sehr flexibel einsetzbar, insbesondere beim Erweitern der Tabelle. Sie müssen nur die angegebenen Daten migrieren und dann die Routing-Tabelle ändern.
Der Nachteil der Routing-Konfiguration besteht darin, dass sie mehr als einmal abgefragt werden muss, was sich auf die Gesamtleistung auswirkt. Wenn die Routing-Tabelle selbst zu groß ist (z. B. Hunderte Millionen Daten), kann dies zu einer Beeinträchtigung der Leistung führen Wird auch zu einem Engpass, wenn wir die Routing-Tabelle erneut in Datenbanken aufteilen. Wenn Sie die Tabelle aufteilen, treten Probleme bei der Auswahl des Endlosschleifen-Routing-Algorithmus auf.
61. Wie erreicht man eine Kapazitätserweiterung ohne Ausfallzeiten?
Tatsächlich ist eine Erweiterung ohne Ausfallzeit in der Praxis ein sehr mühsamer und riskanter Vorgang. Natürlich ist das Interview viel einfacher zu beantworten.
62 Welche Middleware wird häufig zum Sharding von Datenbanken und Tabellen verwendet?
63 Welche Probleme werden Ihrer Meinung nach durch Unterdatenbank und Untertabelle verursacht?
Aus Sicht der Unterdatenbank:
Ein großer Vorteil der Verwendung einer relationalen Datenbank besteht darin, dass sie die Transaktionsintegrität garantiert.
Nach der Aufteilung der Datenbank sind Einzelmaschinentransaktionen nicht mehr erforderlich und müssen mithilfe verteilter Transaktionen gelöst werden.
- Datenbankübergreifendes JOIN-Problem
Wenn wir uns in einer Datenbank befinden, können wir JOIN auch verwenden, um Tabellenabfragen zu verbinden, aber nach dem Überqueren von Datenbanken können wir JOIN nicht verwenden.
Die Lösung zu diesem Zeitpunkt besteht darin, im Geschäftscode zu korrelieren, d .
Diese Methode ist etwas komplizierter in der Umsetzung, aber akzeptabel.
Es gibt auch einige Felder, die entsprechend redundant sein können. In der vorherigen Tabelle wurde beispielsweise eine Korrelations-ID gespeichert, das Unternehmen benötigte jedoch häufig die Rückgabe des entsprechenden Namens oder anderer Felder. Zu diesem Zeitpunkt können diese Felder redundant zur aktuellen Tabelle hinzugefügt werden, um Vorgänge zu entfernen, die eine Zuordnung erfordern.
Eine andere Möglichkeit ist die Datenheterogenität Durch Binlog-Synchronisierung und andere Methoden werden die Daten, die eine datenbankübergreifende Verknüpfung benötigen, in eine Speicherstruktur wie ES heterogen und über ES abgefragt.
Aus der Perspektive von Untertabellen:
- Knotenübergreifende Zählung, Reihenfolge nach, Gruppierung nach und Aggregatfunktionsprobleme
können nur durch Geschäftscode implementiert werden oder Middleware verwenden, um die Daten in jeder Tabelle zusammenzufassen. sortieren, paginieren und zurückgeben.
- Datenmigration, Kapazitätsplanung, Erweiterung und andere Themen
Datenmigration, wie man Kapazitäten plant, ob in Zukunft möglicherweise erneut eine Erweiterung erforderlich ist usw., sind alles Themen, die berücksichtigt werden müssen.
Nachdem die Datenbanktabelle geteilt wurde, kann sie sich nicht mehr auf den eigenen Primärschlüsselgenerierungsmechanismus der Datenbank verlassen. Daher sind einige Mittel erforderlich, um sicherzustellen, dass der globale Primärschlüssel eindeutig ist.
Es ist immer noch die automatische Inkrementierung, aber die Schrittgröße für die automatische Inkrementierung ist festgelegt. Beispielsweise gibt es jetzt drei Tabellen, die Schrittgröße ist auf 3 eingestellt und die anfänglichen ID-Werte der drei Tabellen sind 1, 2 bzw. 3. Auf diese Weise beträgt das ID-Wachstum der ersten Tabelle 1, 4 und 7. Die zweite Tabelle ist 2, 5, 8. Die dritte Tabelle ist 3, 6, 9, daher wird es keine Duplikate geben.
UUID, dies ist die einfachste, aber diskontinuierliche Primärschlüsseleinfügung führt zu schwerwiegenden Seitenaufteilungen und schlechter Leistung.
Verteilte ID, die bekanntere ist der Open-Source-Sonwflake-Snowflake-Algorithmus von Twitter
Betrieb und Wartung
64 Wie lösche ich Daten mit mehr als einer Million Ebenen?
Über den Index: Da der Index zusätzliche Wartungskosten erfordert, da die Indexdatei eine separate Datei ist, werden beim Hinzufügen, Ändern oder Löschen von Daten zusätzliche Vorgänge an der Indexdatei durchgeführt, und diese Vorgänge erfordern zusätzliche E/A-Kosten verringert die Ausführungseffizienz des Hinzufügens/Änderns/Löschens.
Wenn wir also Millionen von Daten in der Datenbank löschen, konsultieren wir das offizielle MySQL-Handbuch und erfahren, dass die Geschwindigkeit des Datenlöschens direkt proportional zur Anzahl der erstellten Indizes ist.
Wenn wir also Millionen von Daten löschen möchten, können wir zuerst den Index löschen
und dann die nutzlosen Daten löschen
Nachdem der Löschvorgang abgeschlossen ist, ist es auch sehr einfach, den Index neu zu erstellen schnell
65. Millionen Wie füge ich Felder zu einer großen Tabelle mit zig Millionen Tabellen hinzu?
Wenn die Menge der Online-Datenbankdaten Millionen oder mehrere zehn Millionen erreicht, ist das Hinzufügen eines Felds nicht so einfach, da die Tabelle möglicherweise für längere Zeit gesperrt ist.
Um Felder zu einer großen Tabelle hinzuzufügen, gibt es normalerweise diese Methoden:
-
Konvertieren Sie sie über eine Zwischentabelle.
Erstellen Sie eine temporäre neue Tabelle, kopieren Sie die Struktur der alten Tabelle vollständig, fügen Sie Felder hinzu und kopieren Sie sie dann Alte Tabellendaten löschen und der neuen Tabelle den Namen der alten Tabelle geben. Diese Methode kann dazu führen, dass einige Daten verloren gehen.
-
Verwenden Sie pt-online-schema-change
pt-online-schema-change , ein von der Firma Percona entwickeltes Tool, das die Tabellenstruktur auch online ändern kann.
-
Fügen Sie es zuerst zur Slave-Datenbank hinzu und führen Sie dann eine Master-Slave-Umschaltung durch.
Wenn eine Tabelle eine große Datenmenge enthält und eine Hot-Tabelle ist (Lesen und Schreiben kommen besonders häufig vor), können Sie erwägen, sie zur hinzuzufügen Erstellen Sie zunächst die Slave-Datenbank und führen Sie dann die Master-Slave-Umschaltung durch. Fügen Sie dann Felder zu mehreren anderen Knoten hinzu.
66. Was soll ich tun, wenn die CPU der MySQL-Datenbank ansteigt?
Fehlerbehebungsprozess:
(1) Verwenden Sie den oberen Befehl, um zu beobachten und festzustellen, ob die Ursache auf MySQL oder andere Gründe zurückzuführen ist.
(2) Wenn es durch mysqld verursacht wird, zeigen Sie die Prozessliste an, überprüfen Sie den Sitzungsstatus und stellen Sie fest, ob ressourcenintensives SQL ausgeführt wird.
(3) Finden Sie die SQL mit hohem Verbrauch heraus und prüfen Sie, ob der Ausführungsplan korrekt ist, ob der Index fehlt und ob die Datenmenge zu groß ist.
Verarbeitung:
(1) Beenden Sie diese Threads (und beobachten Sie, ob die CPU-Auslastung sinkt),
(2) Nehmen Sie entsprechende Anpassungen vor (z. B. Hinzufügen von Indizes, Ändern von SQL, Ändern von Speicherparametern)
(3) Führen Sie diese aus Wieder SQLs.
Andere Situationen:
Es ist auch möglich, dass jede SQL-Anweisung nicht viele Ressourcen verbraucht, aber plötzlich eine große Anzahl von Sitzungsverbindungen eingeht, was zu einem CPU-Anstieg führt. In diesem Fall müssen Sie mit der Anwendung arbeiten Um zu analysieren, warum die Anzahl der Verbindungen ansteigt, nehmen Sie dann entsprechende Anpassungen vor, z. B. die Begrenzung der Anzahl der Verbindungen usw.
[Verwandte Empfehlungen: MySQL-Video-Tutorial]
|
|