<分区>
我正在优化 MySQL 查询,但遇到了一个奇怪的问题。我从不使用实时生产数据库,所以我创建了它的转储,然后使用 mysqldump
将其导入到我本地机器上的数据库中,没有额外的选项。
生产数据库和我本地虚拟机上的mysql版本几乎完全一样:
制作:
mysql Ver 14.14 Distrib 5.1.61,用于使用 readline 6.2 的 debian-linux-gnu (x86_64)
虚拟机:
mysql Ver 14.14 Distrib 5.1.63,用于使用 readline 6.2 的 debian-linux-gnu (x86_64)
这个查询非常复杂,在生产环境中大约需要 4-5 秒,但在 VM 上只需要不到 1 秒。我唯一能想到的是,也许生产数据库上有锁阻止查询立即运行,查询必须等待锁?
针对每个数据库运行查询时的EXTENDED EXPLAIN
几乎相同,只有一些细微差别。
我在查询之前使用 SQL_NO_CACHE
以确保查询不会命中缓存。
所以我的问题是:
- 什么会导致
EXTENDED EXPLAIN
在我使用生产数据库的副本并且 mysql 版本相同时出现差异,即使是轻微的差异?
- 有什么理由我没有想到这会导致相同的查询在生产数据库上花费更长的时间?
有很多因素会影响这个执行时间:
您的生产系统的负载情况如何?你有多少IO余量?如果您的系统正忙于运行其他查询或执行繁重的 IO,则任何查询的性能都会受到严重影响。
通常,您可以使用 SHOW PROCESSLIST
来帮助识别当前正在运行的程序,并使用 iotop
之类的程序来查看正在进行的 IO 量。
您的虚拟机运行的是 SSD 吗?即使是带有 SSD 的中端开发机器,对于任何严重依赖随机访问的东西,也将摧毁几乎所有基于 HD 的数据库服务器。
您是否曾在生产系统上尝试过OPTIMIZE TABLE
?当您进行恢复时,表始终会自动优化。在实时系统上,当您INSERT
和DELETE
行时,该表会慢慢降级。
确保两者都使用相同的存储引擎。 MyISAM 通常比 InnoDB 更快,但在关键数据的生产环境中使用并不安全。使用 SHOW TABLE STATUS
查看每个表使用的引擎。您可能有不同的默认值。
还要检查 /etc/my.cnf
是否进行了相应的调整。 MySQL 的默认配置糟糕。您确实需要为 InnoDB 缓冲区分配更多内存,否则性能会很糟糕。