MySql - 极其缓慢的简单查询(错误的内存配置?)

标签 mysql database performance memory

我有一个非常大的数据库 (~150GB),其中包含许多不同大小的表。它运行在一个相对稳定的服务器上(16GB RAM,8 核 Xeon),无论如何都没有用到它的全部容量(通常是一半的 RAM 和 ~25% 的 CPU)。

但是随着数据库的增长,我遇到越来越多的查询极慢的问题,即使在:

  • 它们看起来优化得很好(至少索引很好)
  • 它们不生成文件排序或 tmp 表
  • 他们不使用内存可能放不下的最大表格

它出现在各种查询中,但这里是一个有时需要超过 1000 万(!)的查询示例:

SELECT A.*, B.*, C.*
    FROM A
    INNER JOIN B USING(id)
    LEFT OUTER JOIN C
        ON (A.id=C.id AND C.date="2016-01-10")
    WHERE A.field1 > 100
      AND  ( B.field2 REGEXP 'XX|YY'
          OR B.field3 REGEXP 'XX|YY' )

这里是 the associated EXPLAIN

表的大小和索引如下:

  • A:25MB 带 INDEX(id)
  • B : 60MB 带 INDEX(id)
  • C : 600MB 带 INDEX(id,date)

好吧,这是对 B 的全表扫描,但只有 200k 行,而且表相对较小(至少它们可以放入内存)。索引似乎很好。那么世界上怎么可能需要超过 1000 万的处理时间呢?

另一个用了 10 多秒的更简单的例子:

SELECT * FROM messages WHERE user_id=1 ORDER BY date ASC

解释说:

select_type     SIMPLE
table           messages
type            ref
possible_keys   user_id
key             user_id
key_len         8
ref             const
rows            5157
Extra           Using index condition; Using where

表 messages 大约 500MB,带有 INDEX(user_id, date)。

请注意,所有表都在使用 myIsam(但这里的问题不在于表锁)。

我怀疑是 mySql 配置不是最优的,阻止它使用空闲内存,从而使它使用磁盘访问,使一切变慢。它也发生在更简单的查询和更小的表中,这一事实似乎也暗示了配置问题。但这只是一个猜测,因为我看不出还有什么可以解释这一点。

另请注意,通常情况下,这些慢速查询在重新执行时(如果不是瞬时的)要快得多(我想是因为缓存)。它们的缓慢还取决于一天中的时刻(我注意到清晨的情况要糟糕得多),而资源永远不会用到满负荷。

有人知道哪里出了问题吗?

提前致谢!

最佳答案

我假设 id 是每个表中的 PRIMARY KEY

C 需要 INDEX(date, id) -- INDEX(date), INDEX( id).

A 需要 INDEX(field1)(但它可能无济于事)

除非您确实需要所有列,否则不要使用 *

如果您不需要LEFT JOIN,请使用JOIN。这样我为 C 提供的索引可能更有用。

事实上,优化器决定对 B 进行全表扫描是唯一有用的开始方式。

请告诉我们REGEXPs到底是什么;可能有改进它们的方法。

messages 需要 INDEX(user_id, date),按此顺序。请提供 SHOW CREATE TABLE 以便我们确认您已经拥有该 2 列复合索引。

改用 InnoDB 应该会有所帮助。

对于 MyISAM,key_buffer_size 应该设置为 可用 RAM 的大约 20%。 (如果你的索引总数(.MYI 文件)小于那个,你可以更低。)在你切换到 InnoDB 之前,innodb_buffer_pool_size 应该是 0。

如果重新执行“立即”运行,那么您正在使用查询缓存。让我们忽略它。但是不要让 query_cache_size 大于 50M。

早上比较慢?也许所有的缓存都是冷的。这可能是因为每晚重启或备份。

关于MySql - 极其缓慢的简单查询(错误的内存配置?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36527951/

相关文章:

mysql - VB.Net Silverlight 项目和 MySQL

mysql - SQL WHERE IN with Left Join 没有返回我期望的所有行

android - SQLite - 从 csv 文件中将带有换行符的字符串插入数据库

php - 如何在mysql中插入\N和带有字符串的制表符?

java - Java 反射的更快替代方案

c# - 仅当记录不存在时才通过存储过程从 TVP 列表中插入项目 - 性能低下

java - 准备好的语句 SQL 错误

mysql - 从具有内部连接和限制的两个表中进行选择

php - 如何根据Id选择分类名称

iOS UIImage.drawInRect(CGContextDrawImage) 性能