Maison  >  Article  >  base de données  >  Plusieurs méthodes d'optimisation MySQL

Plusieurs méthodes d'optimisation MySQL

angryTom
angryTomoriginal
2019-07-20 15:23:0911853parcourir

Plusieurs méthodes d'optimisation MySQL

Tutoriel recommandé : Tutoriel MySQL

1. Choisissez le moteur de stockage approprié : InnoDB

À moins que votre table de données ne soit utilisée pour la récupération en lecture seule ou en texte intégral (je pense que personne n'utilisera MYSQL quand il s'agira à la recherche en texte intégral de nos jours) ). Vous devez sélectionner InnoDB par défaut.

Lorsque vous le testez vous-même, vous constaterez peut-être que MyISAM est plus rapide qu'InnoDB. En effet : MyISAM met uniquement en cache les index, tandis qu'InnoDB met en cache les données et les index, et MyISAM ne prend pas en charge les transactions. Mais en supposant que vous utilisez innodb_flush_log_at_trx_commit = 2, vous pouvez obtenir des performances de lecture proches (une différence de cent fois).

1.1 Comment convertir la base de données MyISAM existante en InnoDB :

mysql -u [USER_NAME] -p -e "SHOW TABLES IN [DATABASE_NAME];" | tail -n +2 | xargs -I '{}' echo "ALTER TABLE {} ENGINE=InnoDB;" > alter_table.sql
perl -p -i -e 's/(search_[a-z_]+ ENGINE=)InnoDB//1MyISAM/g' alter_table.sql
mysql -u [USER_NAME] -p [DATABASE_NAME] < alter_table.sql

1.2 Pour chaque créer un fichier InnoDB pour chaque table :

innodb_file_per_table=1

Cela peut garantir que le fichier ibdata1 ne sera pas trop volumineux. Perdre le contrôle. Surtout lors de l'exécution de mysqlcheck -o –all-databases.

2. Garanti de lire les données de la mémoire. Parler des données stockées en mémoire

2.1 Un innodb_buffer_pool_size suffisamment grand

Il est recommandé de stocker toutes les données dans innodb_buffer_pool_size, c'est-à-dire planifier la capacité de innodb_buffer_pool_size en fonction de la quantité de stockage. De cette façon, vous pouvez lire les données entièrement depuis la mémoire. Minimisez les opérations sur le disque.

2.1.1 Comment déterminer que innodb_buffer_pool_size est suffisamment grand. Les données sont-elles lues depuis la mémoire plutôt que depuis le disque dur ?

Méthode 1

mysql> SHOW GLOBAL STATUS LIKE &#39;innodb_buffer_pool_pages_%&#39;;
+----------------------------------+--------+
| Variable_name                    | Value  |
+----------------------------------+--------+
| Innodb_buffer_pool_pages_data    | 129037 |
| Innodb_buffer_pool_pages_dirty   | 362    |
| Innodb_buffer_pool_pages_flushed | 9998   |
| Innodb_buffer_pool_pages_free    | 0      |  !!!!!!!!
| Innodb_buffer_pool_pages_misc    | 2035   |
| Innodb_buffer_pool_pages_total   | 131072 |
+----------------------------------+--------+
6 rows in set (0.00 sec)

J'ai constaté qu'Innodb_buffer_pool_pages_free est 0, ce qui signifie que le pool de tampons a été utilisé up. Il faut augmenter innodb_buffer_pool_size

Plusieurs autres paramètres d'InnoDB :

innodb_additional_mem_pool_size = 1/200 of buffer_pool
innodb_max_dirty_pages_pct 80%

Méthode 2

Ou utilisez la commande iostat -d -x -k 1 pour vérifier le fonctionnement du disque dur.

2.1.2 S'il y a suffisamment de mémoire sur le serveur pour la planification

Exécutez echo 1 > /sys/vm/drop_caches Efface le cache de fichiers du système d'exploitation. Possibilité de voir la véritable utilisation de la mémoire.

2.2 Réchauffement des données

Par défaut, une donnée ne sera mise en cache que si elle est lue une fois dans innodb_buffer_pool. Par conséquent, la base de données vient de démarrer et doit réchauffer les données et mettre en cache toutes les données du disque dans la mémoire.

Le préchauffage des données peut augmenter la vitesse de lecture.

Pour la base de données InnoDB, vous pouvez utiliser la méthode suivante pour réchauffer les données :

1. Enregistrez le script suivant sous MakeSelectQueriesToLoad.sql

SELECT DISTINCT
    CONCAT(&#39;SELECT &#39;,ndxcollist,&#39; FROM &#39;,db,&#39;.&#39;,tb,
    &#39; ORDER BY &#39;,ndxcollist,&#39;;&#39;) SelectQueryToLoadCache
    FROM
    (
        SELECT
            engine,table_schema db,table_name tb,
            index_name,GROUP_CONCAT(column_name ORDER BY seq_in_index) ndxcollist
        FROM
        (
            SELECT
                B.engine,A.table_schema,A.table_name,
                A.index_name,A.column_name,A.seq_in_index
            FROM
                information_schema.statistics A INNER JOIN
                (
                    SELECT engine,table_schema,table_name
                    FROM information_schema.tables WHERE
                    engine=&#39;InnoDB&#39;
                ) B USING (table_schema,table_name)
            WHERE B.table_schema NOT IN (&#39;information_schema&#39;,&#39;mysql&#39;)
            ORDER BY table_schema,table_name,index_name,seq_in_index
        ) A
        GROUP BY table_schema,table_name,index_name
    ) AA
ORDER BY db,tb
;

2. Exécutez

mysql -uroot -AN < /root/MakeSelectQueriesToLoad.sql > /root/SelectQueriesToLoad.sql

3. Exécutez ceci à chaque fois que vous redémarrez la base de données ou lorsque vous avez besoin de vous réchauffer avant de sauvegarder l'intégralité de la base de données :

mysql -uroot < /root/SelectQueriesToLoad.sql > /dev/null 2>&1

2.3 Ne pas autoriser l'enregistrement des données dans SWAP

En supposant qu'il s'agisse d'un serveur MYSQL dédié. SWAP peut être désactivé, en supposant qu'il s'agit d'un serveur partagé, et assurez-vous que innodb_buffer_pool_size est suffisamment grand. Ou utilisez un espace mémoire fixe pour la mise en cache et utilisez l'instruction memlock.

3. Optimiser et reconstruire régulièrement la base de données

mysqlcheck - o –all-databases permettra à ibdata1 de continuer à croître. La véritable optimisation consiste uniquement à reconstruire la structure de la table de données :

CREATE TABLE mydb.mytablenew LIKE mydb.mytable;
INSERT INTO mydb.mytablenew SELECT * FROM mydb.mytable;
ALTER TABLE mydb.mytable RENAME mydb.mytablezap;
ALTER TABLE mydb.mytablenew RENAME mydb.mytable;
DROP TABLE mydb.mytablezap;

4 Réduire les opérations d'écriture sur le disque

4.1 Utilisez un cache d'écriture suffisamment grand innodb_log_file_size

Mais il convient de noter qu'il est supposé que 1 Go de innodb_log_file_size est utilisé. Si le serveur plante. Il faut 10 minutes pour récupérer.

La taille innodb_log_file_size recommandée est définie sur 0,25 * innodb_buffer_pool_size

4,2 innodb_flush_log_at_trx_commit

  这个选项和写磁盘操作密切相关:

  innodb_flush_log_at_trx_commit = 1 则每次改动写入磁盘

  innodb_flush_log_at_trx_commit = 0/2 每秒写入磁盘

  假设你的应用不涉及非常高的安全性 (金融系统),或者基础架构足够安全,或者 事务都非常小,都能够用 0 或者 2 来减少磁盘操作。

4.3 避免双写入缓冲

innodb_flush_method=O_DIRECT

5. 提高磁盘读写速度

  RAID0 尤其是在使用 EC2 这样的虚拟磁盘 (EBS) 的时候,使用软 RAID0 很重要。

6. 充分使用索引

6.1 查看现有表结构和索引

SHOW CREATE TABLE db1.tb1/G

6.2 加入必要的索引

  索引是提高查询速度的唯一方法。比方搜索引擎用的倒排索引是一样的原理。

  索引的加入须要依据查询来确定。比方通过慢查询日志或者查询日志,或者通过 EXPLAIN 命令分析查询。

ADD UNIQUE INDEX
ADD INDEX

6.2.1 比方,优化用户验证表:

  加入索引

ALTER TABLE users ADD UNIQUE INDEX username_ndx (username);
ALTER TABLE users ADD UNIQUE INDEX username_password_ndx (username,password);

  每次重新启动server进行数据预热

echo “select username,password from users;” > /var/lib/mysql/upcache.sql

  加入启动脚本到 my.cnf

[mysqld]
init-file=/var/lib/mysql/upcache.sql

6.2.2 使用自己主动加索引的框架或者自己主动拆分表结构的框架

  比方。Rails 这种框架。会自己主动加入索引。Drupal 这种框架会自己主动拆分表结构。

  会在你开发的初期指明正确的方向。所以,经验不太丰富的人一開始就追求从 0 開始构建,实际是不好的做法。

7. 分析查询日志和慢查询日志

  记录全部查询。这在用 ORM 系统或者生成查询语句的系统非常实用。

log=/var/log/mysql.log

  注意不要在生产环境用。否则会占满你的磁盘空间。

  记录运行时间超过 1 秒的查询:

long_query_time=1
log-slow-queries=/var/log/mysql/log-slow-queries.log

8. 激进的方法。使用内存磁盘

  如今基础设施的可靠性已经非常高了,比方 EC2 差点儿不用操心server硬件当机。并且内存实在是廉价。非常easy买到几十G内存的server,能够用内存磁盘。定期备份到磁盘。

  将 MYSQL 文件夹迁移到 4G 的内存磁盘

mkdir -p /mnt/ramdisk
sudo mount -t tmpfs -o size=4000M tmpfs /mnt/ramdisk/
mv /var/lib/mysql /mnt/ramdisk/mysql
ln -s /tmp/ramdisk/mysql /var/lib/mysql
chown mysql:mysql mysql

9. 用 NOSQL 的方式使用 MYSQL

  B-TREE 仍然是最高效的索引之中的一个,全部 MYSQL 仍然不会过时。

  用 HandlerSocket 跳过 MYSQL 的 SQL 解析层。MYSQL 就真正变成了 NOSQL。

10. 其它

  ●单条查询最后添加 LIMIT 1,停止全表扫描。

  ●将非”索引”数据分离,比方将大篇文章分离存储,不影响其它自己主动查询。

  ●不用 MYSQL 内置的函数。由于内置函数不会建立查询缓存。

  ●PHP 的建立连接速度很快,全部能够不用连接池。否则可能会造成超过连接数。当然不用连接池 PHP 程序也可能将

  ●连接数占满比方用了 @ignore_user_abort(TRUE);

  ●使用 IP 而不是域名做数据库路径。避免 DNS 解析问题

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn