【问题标题】:Mysql performance with low memory内存不足的mysql性能
【发布时间】:2016-04-05 08:21:10
【问题描述】:

我的服务器上的 mysql 存在严重的性能问题。我有一个很大的表,不是特别是行数(~900 000 行),而是更多的列数(~90 列)和很多索引(~30 个索引)(这是一个 Innodb 表)。

当我在一段时间内没有进行任何查询后从表中执行计数(*)时,查询可能需要很长时间,这是显示进程列表的结果:

| Command | Time | State        | Info                                                                                      |
| Query   | 430  | Sending data | SELECT COUNT(*) FROM CATALOG where PUBLISH = 1 and (Exclusions = 2 or Exclusions is null) |

几乎 1000 万个计数(*),然后当我在没有缓存的情况下尝试它时:

mysql> SELECT SQL_NO_CACHE COUNT(*) FROM CATALOG where PUBLISH = 1 and (Exclusions = 2 or Exclusions is null);
+----------+
| COUNT(*) |
+----------+
|   900872 |
+----------+
1 row in set (0.66 sec)

或者使用缓存:

mysql> SELECT COUNT(*) FROM CATALOG where PUBLISH = 1 and (Exclusions = 2 or Exclusions is null);
+----------+
| COUNT(*) |
+----------+
|   900872 |
+----------+
1 row in set (0.00 sec)

mysql 可以在这张表上为 1000 万做什么?也许是内存不足?服务器上的交换非常高......

编辑:这里是查询的解释

mysql> explain SELECT COUNT(*) FROM CATALOG where PUBLISH = 1 and (Exclusions = 2 or Exclusions is null);
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | CATALOG | ALL  | NULL          | NULL | NULL    | NULL | 905537 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+
1 row in set (0.14 sec)

【问题讨论】:

  • count(*) 使用每一列。如果你使用 COUNT(1) 怎么办?
  • ^ 是的,具体一点,也可能您的索引不适合您的查询。因此,它不再使用索引,而是恢复为全表扫描。
  • 您是否对计数查询进行了解释,以查看它可能使用的 30 个索引中的哪个(如果有)?
  • 没有使用索引,可能查询不是很优化但它没有解释为什么有时它花费1000万来做它,而它花费0.66s来做它没有缓存。我添加了解释。
  • 我想知道mysql是否没有重新计算所有表索引,我真的不知道索引是如何工作的,我不知道是否有可能。但它可以解释为什么要花费 1000 万,在这样的表上创建 30 个索引应该花费这么多时间。

标签: php mysql performance


【解决方案1】:

请提供SHOW CREATE TABLESHOW TABLE STATUS LIKE 'CATALOG';

30 个索引很多。

INDEX(PUBLISH, Exclusions)

将是 this 查询的最佳索引。 EXPLAIN 会说 Using index 而不是 Using where

基于EXPLAIN,做了一次表扫描; 0.66s还不错。缓存的版本无关紧要;它在“查询缓存”中找到了查询,并在没有做任何实际工作的情况下返回了结果。 InnoDB 有它的“buffer_pool”,它似乎包含了整个表,因此是 0.66s,显然没有任何 I/O。

innodb_buffer_pool_size 的值是多少?

“这个表上 1000 万个 mysql 能做什么?” - 你在问什么;什么是'mn'? MySQL 几乎可以处理任何大小的表。随着表变大,表扫描需要更长的时间。一旦表变得比 buffer_pool 大,表扫描将成为 I/O 密集型的,并且此查询将显着减慢。但它会(最终)完成。 (我在您的输出中没有看到“10 分钟”。)

如果你将 MySQL 配置为使用过多的 RAM,以至于它“交换”,性能将会变得非常非常糟糕。单线规则:buffer_pool 应该是大约 70% 或可用 RAM。越小效率越低;更大的威胁要交换。

这张表是什么引擎?如果是 MyISAM,那么其他一些操作可能会锁定表。一般来说,InnoDB 更好。

COUNT(*) 是正常的表达方式; COUNT(1) 以同样的努力为您提供相同的答案。 COUNT(col) 增加了检查 col 是否为 NULL 的负担。

除非您通过ALTEROPTIMIZE 请求,否则MySQL 不会重建索引。索引是增量维护的。除了极少数例外,它们总是接近最佳格式。

在不知道问题原因的情况下,将内存翻倍可能并不划算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多