【问题标题】:MySQL: Slow avg query for 411M rowsMySQL:4.11 亿行的慢速平均查询
【发布时间】:2015-11-05 08:13:44
【问题描述】:

我有一个简单的表(由 django 创建)-引擎 InnoDB:

+-------------+------------------+------+-----+---------+----------------+
| Field       | Type             | Null | Key | Default | Extra          |
+-------------+------------------+------+-----+---------+----------------+
| id          | int(11)          | NO   | PRI | NULL    | auto_increment |
| correlation | double           | NO   |     | NULL    |                |
| gene1_id    | int(10) unsigned | NO   | MUL | NULL    |                |
| gene2_id    | int(10) unsigned | NO   | MUL | NULL    |                |
+-------------+------------------+------+-----+---------+----------------+

该表有超过 4.11 亿行。 (目标表大约有 461M 行,21471*21470 行)

我的主要查询是这样的,最多指定10个基因。

 SELECT gene1_id, AVG(correlation) AS avg FROM genescorrelation 
 WHERE gene2_id IN (176829, 176519, 176230) 
 GROUP BY gene1_id ORDER BY NULL 

这个查询很慢,运行大约需要 2 分钟:

21471 rows in set (1 min 11.03 sec)

索引(基数看起来很奇怪 - 太小了?):

  Non_unique| Key_name                                         | Seq_in_index | Column_name | Collation | Cardinality |
          0 | PRIMARY                                          |            1 | id          | A         |   411512194 | 
          1 | c_gene1_id_6b1d81605661118_fk_genes_gene_entrez  |            1 | gene1_id    | A         |          18 |
          1 | c_gene2_id_2d0044eaa6fd8c0f_fk_genes_gene_entrez |            1 | gene2_id    | A         |          18 | 

我只是在该表上运行 select count(*),它花了 22 分钟:

select count(*) from predictions_genescorrelation;

+-----------+
| count(*)  |
+-----------+
| 411512002 |
+-----------+
1 row in set (22 min 45.05 sec)

可能出了什么问题? 我怀疑mysql配置没有设置好。

在导入数据期间,我遇到了空间问题,因此这也可能影响数据库,尽管我后来运行了check table - 花了 2 小时并表示 OK。

此外 - 索引的基数看起来很奇怪。我在本地设置了较小的数据库,并且值完全不同(254945589,56528,17)。

我应该重做索引吗? 我应该检查 MySQL 的哪些参数? 我的表设置为 InnoDB,MyISAM 有什么不同吗?

谢谢, 马塔利

【问题讨论】:

  • 我认为这个问题更适合dba.stackexchange.com,因为它涉及的配置多于查询性能。
  • 对于这样的查询,我会创建一个索引(gene2_id, gene1_id, correlation)。此外,id 序列号可能完全没用,你有没有在 WHERE 条件下使用它?你的逻辑主键是什么,(gene2_id, gene1_id)
  • 你需要id吗? PRIMARY KEY(gene2_id, gene1_id) 似乎是独一无二的,而且速度更快。此外,gene_ids 可以是 SMALLINT UNSIGNED 为 2 个字节,而不是当前的 2 个字节。
  • 继续使用 InnoDB。但是检查innodb_buffer_pool_size;它应该是 RAM 的 70% 左右。如果它比桌子大,那就特别好。
  • 搁置它的逻辑是假的。这是一个优化问题,有很多答案,其中大多数是正交的和可加的。

标签: mysql sql average database-performance


【解决方案1】:

https://www.percona.com/blog/2006/12/01/count-for-innodb-tables/

SELECT COUNT(*) 查询在没有WHERE 子句或没有SELECT COUNT(id) ... USE INDEX (PRIMARY) 时非常慢。

加快速度:

 SELECT gene1_id, AVG(correlation) AS avg FROM genescorrelation 
 WHERE gene2_id IN (176829, 176519, 176230) 
 GROUP BY gene1_id ORDER BY NULL

您应该按该顺序在 (gene2_id,gene1_id,correlation) 上有复合键。试试

关于索引基数:Innodb 表的统计数据是近似的,不准确(有时很疯狂)。甚至有(是?)错误报告https://bugs.mysql.com/bug.php?id=58382

再次尝试分析表并观察基数

【讨论】:

  • 谢谢!基数更改为 411512194、95522、95522。现在正在处理索引。
  • 它不会很快))处理索引。试试gene2_id,gene1_id。不是 3 个部分
  • 是的。如果没有帮助,那么gene2_id,gene1_id,相关性
  • 创建索引时遇到:错误 1034 (HY000):表 'predictions_genescorrelation' 的密钥文件不正确;尝试修复它。
猜你喜欢
  • 1970-01-01
  • 2016-01-10
  • 2016-06-08
  • 2021-04-21
  • 1970-01-01
  • 2012-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多