如何将 MySQL 查询速度提高 300 倍

546 位读者喜欢此文。
Open lightbulbs.

Opensource.com

在分析慢查询之前,您需要找到它们。

MySQL 有一个内置的慢查询日志。 要使用它,请打开 my.cnf 文件并将 slow_query_log 变量设置为 "On"。 将 long_query_time 设置为查询被视为慢查询所需的秒数,例如 0.2。 将 slow_query_log_file 设置为您要保存文件的路径。 然后运行您的代码,任何高于指定阈值的查询都将被添加到该文件中。

一旦你知道哪些是慢查询,你可以开始探索是什么使它们变慢。 MySQL 提供的一个工具是 EXPLAIN 关键字。 它适用于 SELECT, DELETE, INSERT, REPLACE, 和 UPDATE 语句。 您只需像这样在查询前添加前缀

EXPLAIN SELECT picture.id, picture.title

FROM picture

LEFT JOIN album ON picture.album_id = album.id

WHERE album.user_id = 1;

您得到的结果是对数据访问方式的解释。 您会看到查询中涉及的每个表的一行

An explanation of how data is accessed

这里重要的部分是表名,使用的键以及查询执行期间扫描的行数。

The important pieces here are the table name, the key used, and the number of rows scanned.

它扫描了 2,000,000 张图片,然后,对于每张图片,它扫描了 20,000 个相册。 这意味着它实际上扫描了 album 表的 400 亿行。 但是,您可以使此过程更加高效。

索引

您可以通过使用索引来显着提高性能。 将数据视为地址簿中的名称。 您可以翻阅所有页面,也可以拉动正确的字母标签以快速找到所需的名称。

使用索引避免不必要地遍历表。 例如,您可以像这样在 picture.album_id 上添加索引

ALTER TABLE picture ADD INDEX(album_id);

现在,如果您运行查询,该过程不再涉及扫描整个图片列表。 首先,扫描所有相册以查找属于用户的相册。 之后,使用索引的 album_id 列快速定位图片。 这将扫描的行数减少到 200,000。 查询速度也比原来快 317 倍。

The query is also about 317 times faster than the original.

您可以通过添加以下索引来确保两个表都使用键

ALTER TABLE album ADD INDEX(user_id);

Make sure that both tables use a key

这次,album 表没有被完整扫描,而是使用 user_id 键快速准确定位了正确的相册。 扫描这 100 个相册后,使用 album_id 键准确定位相关图片。 每个表都使用一个键来实现最佳性能,使查询速度比原来快 380 倍。

这并不意味着您应该在所有地方都添加索引,因为每个索引都会延长写入数据库的时间。 你在读取时获得优势,但在写入时失去优势。 因此,只添加实际提高读取性能的索引。 使用 EXPLAIN 确认并删除查询中未使用的任何索引。

有很多其他方法可以提高性能,您可以在我的 OSCON 演讲 Speed Up You Database 300 Times 中了解更多信息。

Anna 将在德克萨斯州奥斯汀的 OSCON 2017 上发表演讲 Speed Up You Database 300 Times。 如果您有兴趣参加会议,请使用此折扣码 在您注册时,为我们的读者:PCOS

标签
Closeup of Anna Filina on stage with a head microphone.
Anna 是一位 Web 开发人员、项目救援专家、Pluralsight 作者、演讲者和会议组织者。 她喜欢实现看似不可能的事情。 她从 1997 年开始编码。

5 条评论

当然,使用关系数据库的全部意义在于规范化。 您拥有 "album_id" 和 "user_id" 字段这一事实表明数据库已规范化。 在大多数关系数据库系统中,如果数据库已正确规范化,则表是索引(在主键上)。 当然,二级键可能会提高奇怪查询的性能,但是,如果查询如此奇怪 - 如不频繁 - 通常最好*不要*创建另一个索引。 为不频繁的查询维护索引的开销可能会导致整体性能下降。

当然,这都是 RDBMS 入门知识,但我想您知道这一点。

天哪,这真是 RDBMS 101。 它还鼓励新手像盐和胡椒一样使用索引 - 不知道维护索引也需要时间,并且会大大降低删除、更新和插入的速度。 我想演示文稿的其余部分花费在其他 101 个项目上,例如触发完整表扫描的函数,并且整数键比字符串 ID 快。

完全具有误导性的标题。 它应该命名为 "MySQL for beginners",因为这确实是 DBA 的数据库 101。 鲜为人知的是,大多数 SQL 函数完全忽略索引并引发完整表扫描。 或者像胡椒和盐一样添加索引实际上会降低数据库的速度。 或者完全适用于一种 RDBMS 的 SQL 不一定在另一种 RDBMS 上表现良好。 下次做一些花哨的临时表或东西并赢得那个称号。 我不明白为什么它进入前 5 名。

对于 MySQL,视图优化通常是更大的胜利。 从视图连接到任何表会隐藏所有索引,除了连接到的表上的索引。 因此,一旦你开始连接,你在 where 子句中引用的任何内容都需要来自表连接引用,否则你将从临时表中获得表扫描性能,这将在多用户环境中大大降低性能!

Creative Commons License本作品采用 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.