【问题标题】:What is the best way to optimze this query with indexes?使用索引优化查询的最佳方法是什么?
【发布时间】:2012-07-14 06:27:31
【问题描述】:

我有一个包含大约 3000 万条记录的表,我需要对其执行查询。根据我的阅读,我认为使用最左前缀和我需要选择的所有字段的复合索引是正确的方法,但是当我对查询运行解释时,它甚至没有使用索引。

这是查询:

select distinct email FROM my_table 
WHERE `customer_id` IN(278,428,186,40,208,247,59,79,376,73,38,52,68,227) 
AND `company_id` = 4 
AND `active` = 1 
AND `date` > '2012-04-15';

解释是这样的

+----+-------------+--------+-------+---------------+-------+---------+------+----------+-------------+
| id | select_type | table  | type  | possible_keys | key   | key_len | ref  | rows     | Extra       |
+----+-------------+--------+-------+---------------+-------+---------+------+----------+-------------+
|  1 | SIMPLE      | emails | index | customer_id   | email | 772     | NULL | 29296705 | Using where |
+----+-------------+--------+-------+---------------+-------+---------+------+----------+-------------+

这些是字段

`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL DEFAULT '',
`customer_id` int(10) unsigned DEFAULT NULL, 
`company_id` int(10) unsigned NOT NULL,
`active` tinyint(1) unsigned NOT NULL DEFAULT '1',                                                                                                                                            
`date` date DEFAULT NULL

索引看起来像这样

PRIMARY KEY (`id`),                                                                                                                                                                                                                        
UNIQUE KEY `email` (`email`,`customer_id`),                                                                                                                                                                                                
KEY `customer_id` (`customer_id`,`company_id`,`active`,`date`) 

我不太确定优化它的最佳方法是什么。

【问题讨论】:

  • @radashk 查询仅返回 3,117,636 行。在说明中,它显示有近 3000 万行需要过滤。
  • 这些都是您使用 WHERE IN 子句的所有情况。它无法索引。
  • 没有一种方法或最好的方法来提高性能,您必须采用不同的方法,直到找到最佳解决方案

标签: mysql select indexing key explain


【解决方案1】:

MySQL 经常对索引左侧的IN 很挑剔。为每个customer_id 尝试一个查询,看看它是否使用了您的索引。您可以使用UNION 语法将它们连接在一起。另一种可能性是,MySQL 认为筛选 10% 的行的所有内容比尝试为它们使用索引要快。

【讨论】:

  • 当我这样做时它确实使用了索引。我还注意到,如果我做一个 force index(customer_id),解释只会显示 630 万,这是一个巨大的改进。
  • 我会为这两个查询计时,每个查询运行几次。 MySQL 认为不使用索引会更快,而且可能是对的。
  • 两个查询各运行 5 次,使用 FORCE INDEX 绝对是一种改进。原始查询的时间分别为 26.4、25.4、27.7、25.1 和 25.5。 FORCE INDEX 查询的时间分别为 14.1、14.3、14.3、13.9 和 14.9。
  • 所以,默认情况下 MySQl 并没有做最好的事情,你必须通过 FORCE INDEX 来帮助它。作为最后的努力,您可以尝试运行ANALYZE TABLE 以查看这是否有助于它默认选择索引。 dev.mysql.com/doc/refman/5.0/en/analyze-table.html
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多