Heim  >  Artikel  >  Datenbank  >  Interviewfrage: Wie optimiert man MySQL im Arbeitsalltag?

Interviewfrage: Wie optimiert man MySQL im Arbeitsalltag?

Java后端技术全栈
Java后端技术全栈nach vorne
2023-08-17 16:26:10984Durchsuche

Vorwort

Die gängigen Optimierungsmethoden von MySQL sind in die folgenden Aspekte unterteilt:

SQL-Optimierung, Designoptimierung, Hardwareoptimierung usw., die jeweils mehrere kleine Optimierungen umfassen

Interviewfrage: Wie optimiert man MySQL im Arbeitsalltag? Schauen wir uns unten einen genaueren Blick an

SQL-OptimierungDieser Optimierungsplan bezieht sich auf die Verbesserung der Betriebseffizienz der MySQL-Datenbank durch Optimierung von SQL-Anweisungen und -Indizes. Der spezifische Inhalt lautet wie folgt:

Paging-OptimierungZum Beispiel:

select * from table where type = 2 and level = 9 order by id asc limit 190289,10;

Optimierungsplan:

  • Verzögerte Zuordnung

    Zuerst den Primärschlüssel über die Where-Bedingung extrahieren, dann die Tabelle mit der Originaldatentabelle verknüpfen und die Datenzeilen über die extrahieren Primärschlüssel-ID, anstatt Datenzeilen über den ursprünglichen Sekundärindex zu extrahieren erster Parameter des Limits und dann basierend auf diesem Primärschlüsselwert Gehen Sie zu Filter und Limit

    Zum Beispiel:

    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
  • Indexoptimierung

    Index richtig verwenden

    假如我们没有添加索引,那么在查询时就会触发全表扫描,因此查询的数据就会很多,并且查询效率会很低,为了提高查询的性能,我们就需要给最常使用的查询字段上,添加相应的索引,这样才能提高查询的性能

    建立覆盖索引

    InnoDB使用辅助索引查询数据时会回表,但是如果索引的叶节点中已经包含要查询的字段,那它没有必要再回表查询了,这就叫覆盖索引

    例如对于如下查询:

    select name from test where city='上海'

    我们将被查询的字段建立到联合索引中,这样查询结果就可以直接从索引中获取

    alter table test add index idx_city_name (city, name);

    在 MySQL 5.0 之前的版本尽量避免使用or查询

    在 MySQL 5.0 之前的版本要尽量避免使用 or 查询,可以使用 union 或者子查询来替代,因为早期的 MySQL 版本使用 or 查询可能会导致索引失效,在 MySQL 5.0 之后的版本中引入了索引合并

    索引合并简单来说就是把多条件查询,比如or或and查询对多个索引分别进行条件扫描,然后将它们各自的结果进行合并,因此就不会导致索引失效的问题了

    如果从Explain执行计划的type列的值是index_merge可以看出MySQL使用索引合并的方式来执行对表的查询

    避免在 where 查询条件中使用 != 或者 a8093152e673feb7aba1828c43532094 操作符

    SQL中,不等于操作符会导致查询引擎放弃索引索引,引起全表扫描,即使比较的字段上有索引

    解决方法:通过把不等于操作符改成or,可以使用索引,避免全表扫描

    例如,把columna8093152e673feb7aba1828c43532094’aaa’,改成column>’aaa’ or column<’aaa’,就可以使用索引了

    适当使用前缀索引

    MySQL 是支持前缀索引的,也就是说我们可以定义字符串的一部分来作为索引

    我们知道索引越长占用的磁盘空间就越大,那么在相同数据页中能放下的索引值也就越少,这就意味着搜索索引需要的查询时间也就越长,进而查询的效率就会降低,所以我们可以适当的选择使用前缀索引,以减少空间的占用和提高查询效率

    比如,邮箱的后缀都是固定的“@xxx.com”,那么类似这种后面几位为固定值的字段就非常适合定义为前缀索引

    alter table test add index index2(email(6));

    使用前缀索引,定义好长度,就可以做到既节省空间,又不用额外增加太多的查询成本

    需要注意的是,前缀索引也存在缺点,MySQL无法利用前缀索引做order by和group by 操作,也无法作为覆盖索引

    查询具体的字段而非全部字段

    要尽量避免使用select *,而是查询需要的字段,这样可以提升速度,以及减少网络传输的带宽压力

    优化子查询

    尽量使用 Join 语句来替代子查询,因为子查询是嵌套查询,而嵌套查询会新创建一张临时表,而临时表的创建与销毁会占用一定的系统资源以及花费一定的时间,同时对于返回结果集比较大的子查询,其对查询性能的影响更大

    小表驱动大表

    我们要尽量使用小表驱动大表的方式进行查询,也就是如果 B 表的数据小于 A 表的数据,那执行的顺序就是先查 B 表再查 A 表,具体查询语句如下:

    select name from A where id in (select id from B);

    不要在列上进行运算操作

    不要在列字段上进行算术运算或其他表达式运算,否则可能会导致查询引擎无法正确使用索引,从而影响了查询的效率

    select * from test where id + 1 = 50;
    select * from test where month(updateTime) = 7;

    一个很容易踩的坑:隐式类型转换:

    select * from test where skuId=123456

    skuId这个字段上有索引,但是explain的结果却显示这条语句会全表扫描

    原因在于skuId的字符类型是varchar(32),比较值却是整型,故需要做类型转换

    适当增加冗余字段

    增加冗余字段可以减少大量的连表查询,因为多张表的连表查询性能很低,所有可以适当的增加冗余字段,以减少多张表的关联查询,这是以空间换时间的优化策略

    正确使用联合索引

    使用了 B+ 树的 MySQL 数据库引擎,比如 InnoDB 引擎,在每次查询复合字段时是从左往右匹配数据的,因此在创建联合索引的时候需要注意索引创建的顺序

    例如,我们创建了一个联合索引是idx(name,age,sex),那么当我们使用,姓名+年龄+性别、姓名+年龄、姓名等这种最左前缀查询条件时,就会触发联合索引进行查询;然而如果非最左匹配的查询条件,例如,性别+姓名这种查询条件就不会触发联合索引

    Join优化

    MySQL的join语句连接表使用的是nested-loop join算法,这个过程类似于嵌套循环,简单来说,就是遍历驱动表(外层表),每读出一行数据,取出连接字段到被驱动表(内层表)里查找满足条件的行,组成结果行

    要提升join语句的性能,就要尽可能减少嵌套循环的循环次数

    一个显著优化方式是对被驱动表的join字段建立索引,利用索引能快速匹配到对应的行,避免与内层表每一行记录做比较,极大地减少总循环次数。另一个优化点,就是连接时用小结果集驱动大结果集,在索引优化的基础上能进一步减少嵌套循环的次数

    如果难以判断哪个是大表,哪个是小表,可以用inner join连接,MySQL会自动选择小表去驱动大表

    避免使用JOIN关联太多的表

    对于 MySQL 来说,是存在关联缓存的,缓存的大小可以由join_buffer_size参数进行设置

    在 MySQL 中,对于同一个 SQL 多关联(join)一个表,就会多分配一个关联缓存,如果在一个 SQL 中关联的表越多,所占用的内存也就越大

    如果程序中大量的使用了多表关联的操作,同时join_buffer_size设置的也不合理的情况下,就容易造成服务器内存溢出的情况,就会影响到服务器数据库性能的稳定性

    排序优化

    利用索引扫描做排序

    MySQL有两种方式生成有序结果:其一是对结果集进行排序的操作,其二是按照索引顺序扫描得出的结果自然是有序的

    但是如果索引不能覆盖查询所需列,就不得不每扫描一条记录回表查询一次,这个读操作是随机IO,通常会比顺序全表扫描还慢

    因此,在设计索引时,尽可能使用同一个索引既满足排序又用于查找行

    例如:

    --建立索引(date,staff_id,customer_id)
    select staff_id, customer_id from test where date = &#39;2010-01-01&#39; order by staff_id,customer_id;

    只有当索引的列顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向都一样时,才能够使用索引来对结果做排序

    UNION优化

    MySQL处理union的策略是先创建临时表,然后将各个查询结果填充到临时表中最后再来做查询,很多优化策略在union查询中都会失效,因为它无法利用索引

    最好手工将where、limit等子句下推到union的各个子查询中,以便优化器可以充分利用这些条件进行优化

    此外,除非确实需要服务器去重,一定要使用union all,如果不加all关键字,MySQL会给临时表加上distinct选项,这会导致对整个临时表做唯一性检查,代价很高

    慢查询日志

    出现慢查询通常的排查手段是先使用慢查询日志功能,查询出比较慢的 SQL 语句,然后再通过 Explain 来查询 SQL 语句的执行计划,最后分析并定位出问题的根源,再进行处理

    Langsames Abfrageprotokoll bezieht sich auf die Aufzeichnungsfunktion eines langsamen Abfrageprotokolls, das über die Konfiguration in MySQL aktiviert werden kann und long_query_time Der Wert von SQL wird im Protokoll aufgezeichnetlong_query_time值的 SQL 将会被记录在日志中

    我们可以通过设置“slow_query_log=1”

    Wir können "slow_query_log=1" um die langsame Abfrage zu aktivieren

    Es ist zu beachten, dass sich dies nach dem Einschalten der langsamen Protokollfunktion auf die Funktion auswirkt Leistung von MySQL Es wird eine gewisse Auswirkung haben, daher sollte diese Funktion in der Produktionsumgebung mit Vorsicht verwendet werden. Versuchen Sie, die Verwendung von NULL-Operatoren zu vermeiden. Spalten, die NULL enthalten, sind schwierig zu optimieren nicht null, und der Nullwert sollte durch 0, eine leere Zeichenfolge oder einen anderen Sonderwert ersetzt werden, z. B. als int not null Standardwert 0 definiert und CPU-Cache und sind schneller zu verarbeiten

    Verwenden Sie die einfachsten Datentypen

    Einfache Datentypoperationen sind billiger, wie zum Beispiel: Wenn Sie den Typ int verwenden können, verwenden Sie nicht den Typ varchar, da der Typ int dies ist effizienter als der Typ varchar beim Abfragen. Die Effizienz der Texttyp-Abfrage ist sehr gering. Wenn Sie Text zum Definieren von Feldern verwenden müssen, können Sie dieses Feld in eine Untertabelle aufteilen Sie müssen dieses Feld abfragen und eine gemeinsame Abfrage verwenden, um die Abfrageeffizienz der Haupttabelle zu verbessern.

    Geeignete Strategie für Untertabellen und Unterdatenbanken. Untertabelle bedeutet, dass eine Tabelle mehr Felder enthält. Sie können versuchen, eine große Tabelle in mehrere Untertabellen aufzuteilen, die am häufigsten verwendeten Hauptinformationen in die Haupttabelle und die anderen in Untertabellen einzufügen. Auf diese Weise müssen die meisten unserer Abfragen nur die Haupttabelle abfragen mit weniger Feldern, wodurch die Abfrageeffizienz effektiv verbessert wird. Unter „Unterdatenbank“ versteht man die Aufteilung einer Datenbank in mehrere Datenbanken. Beispielsweise teilen wir eine Datenbank in mehrere Datenbanken auf, um Daten zu schreiben und zu ändern, und die anderen dienen dazu, die Hauptdaten zu synchronisieren und sie dem Client zum Lesen und Schreiben bereitzustellen Der Druck einer Datenbank wird geteilt, wodurch die Gesamtbetriebseffizienz der Datenbank verbessert wird

    Gemeinsame Typauswahl

    Einstellung der Breite des Ganzzahltyps

    MySQL kann die Breite für Ganzzahltypen wie int(11) angeben, was eigentlich keinen Sinn ergibt und den Wertebereich nicht einschränkt. Für die Speicherung und Berechnung sind int(1) und int(20) gleich

    VARCHAR- und CHAR-Typen

    char-Typ hat eine feste Länge, und varchar speichert variable Zeichenfolgen, was mehr Platz spart als feste Länge, aber varchar Es Zum Aufzeichnen der Zeichenfolgenlänge sind 1 oder 2 zusätzliche Bytes erforderlich, und es besteht auch die Gefahr einer Fragmentierung beim Aktualisieren. Die Auswahl muss je nach Verwendungsszenario erfolgen: Wenn die maximale Länge der Zeichenfolgenspalte viel größer als die durchschnittliche Länge ist, oder die Spalte wird selten aktualisiert, es ist bequemer, Varchar zu wählen. Geeignet, wenn Sie eine sehr kurze Zeichenfolge speichern möchten oder die Zeichenfolgenwerte dieselbe Länge haben, z. B. MD5-Werte, oder sich die Spaltendaten häufig ändern , wählen Sie die Verwendung der Typen char

    DATETIME und TIMESTAMP-Typen

    datetime hat einen größeren Bereich und kann die Jahre von 1001 bis 9999 darstellen, und der Zeitstempel kann nur die Jahre von 1970 bis 2038 darstellen. datetime hat nichts mit der Zeitzone zu tun, der Anzeigewert des Zeitstempels hängt von der Zeitzone ab. In den meisten Szenarien können beide Typen gut funktionieren, es wird jedoch empfohlen, Zeitstempel zu verwenden, da Datum/Uhrzeit 8 Bytes belegt, Zeitstempel nur 4 Bytes und der Platz für Zeitstempel effizienter ist. BLOB- und TEXT-Typen. Blob und Text sind beides Zeichenfolgendatentypen, die zum Speichern großer Datenmengen entwickelt wurden. Sie werden im Binär- bzw. Zeichenmodus gespeichert. Bei der tatsächlichen Verwendung sollten diese beiden Typen mit Vorsicht verwendet werden, da ihre Abfrageeffizienz sehr gering ist Typen können Sie dieses Feld in eine Untertabelle aufteilen. Wenn Sie dieses Feld abfragen müssen, verwenden Sie eine gemeinsame Abfrage, die die Abfrageeffizienz der Haupttabelle verbessern kann ein besseres Paradigma Beim Normalisieren werden weniger Daten geändert, und die normalisierte Tabelle ist normalerweise kleiner, und mehr Daten können im Speicher zwischengespeichert werden, sodass der Ausführungsvorgang schneller erfolgt

    Der Nachteil besteht darin, dass während der Abfrage mehr Zuordnungen erforderlich sind

    Kapitel Erste Normalform: Felder sind untrennbar und die Datenbank unterstützt dies standardmäßig: Eliminiert die teilweise Abhängigkeit vom Primärschlüssel. Sie können ein Feld, das nichts mit der Geschäftslogik zu tun hat, als Primärschlüssel hinzufügen B. die Verwendung einer Auto-Inkrement-ID. Dritte Normalform: Eliminieren Sie die transitive Abhängigkeit vom Primärschlüssel und teilen Sie die Tabelle auf, um die Datenredundanz zu reduzieren

    Hardware-Optimierung

    Die Hardwareanforderungen von MySQL spiegeln sich hauptsächlich in drei Aspekten wider: Festplatte, Netzwerk und Speicher. Auf diese Weise kann die E/A-Laufzeit reduziert und die Gesamtbetriebseffizienz von MySQL verbessert werden. Bei Festplatten können Sie auch versuchen, mehrere kleine Festplatten anstelle einer großen Festplatte zu verwenden Festplatte ist gleichbedeutend damit, dass mehrere Festplatten parallel laufen

    Netzwerk

    Die Gewährleistung einer reibungslosen Netzwerkbandbreite (geringe Latenz) und ausreichender Netzwerkbandbreite sind die Grundvoraussetzungen für den normalen Betrieb von MySQL Richten Sie außerdem mehrere Netzwerkkarten ein, um die Betriebseffizienz des MySQL-Servers während Netzwerkspitzenzeiten zu verbessern Der Speicher ist sehr hoch, wodurch die gesamte MySQL-Betriebseffizienz verbessert wird

Das obige ist der detaillierte Inhalt vonInterviewfrage: Wie optimiert man MySQL im Arbeitsalltag?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:Java后端技术全栈. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen
Vorheriger Artikel:SQL in der Operator-NutzungNächster Artikel:SQL in der Operator-Nutzung