mysql - 创建索引的顺序会影响查询优化器将选择哪个索引?

标签 mysql

如果我创建以下两个索引

ALTER TABLE requests ADD INDEX daily_ips(exec_date, ip_address);
ALTER TABLE requests ADD INDEX is_cached(exec_date, cached);

show index from requests 的输出如下

Table       Non_unique  Key_name    Seq_in_index    Column_name Collation   Cardinality Sub_part    Packed  Null    Index_type  Comment Index_comment
requests    1           daily_ips   1               exec_date   A           413         NULL    NULL    YES BTREE       
requests    1           daily_ips   2               ip_address  A           218334      NULL    NULL    YES BTREE       
requests    1           is_cached   1               exec_date   A           165         NULL    NULL    YES BTREE       
requests    1           is_cached   2               cached      A           165         NULL    NULL    YES BTREE       

我有以下查询

EXPLAIN SELECT exec_date,
    100 * SUM(CASE WHEN cached = 'no' THEN 1 ELSE 0 END)  / SUM(1) cached_no,
    100 * SUM(CASE WHEN cached != 'no' THEN 1 ELSE 0 END)  / SUM(1) cached_yes
FROM requests
GROUP BY exec_date;

id  select_type table   type    possible_keys   key         key_len ref rows    Extra
1   SIMPLE  requests    index   NULL            daily_ips   263 NULL    436695  

但是我想强制查询优化器使用 is_cached 索引而不是 daily_ips 索引。

如果我删除 daily_ips 索引并再次添加它

ALTER TABLE requests DROP INDEX daily_ips;
ALTER TABLE requests ADD INDEX daily_ips(exec_date, ip_address);

然后运行相同的 EXPLAIN 语句,查询优化器选择 is_cached 索引。

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  requests    index   NULL    is_cached   6   NULL    440493  Using index

查询优化器根据添加顺序选择索引是否符合预期?

我如何告诉查询优化器使用哪个索引?

最佳答案

您可以指定查询运行时应使用哪个索引。

试试这个:

EXPLAIN SELECT exec_date,
    100 * SUM(CASE WHEN cached = 'no' THEN 1 ELSE 0 END)  / SUM(1) cached_no,
    100 * SUM(CASE WHEN cached != 'no' THEN 1 ELSE 0 END)  / SUM(1) cached_yes
FROM requests USE INDEX(is_cached)
GROUP BY exec_date;

USE INDEXFORCE INDEX 的区别:

通过指定 USE INDEX (index_list),您可以告诉 MySQL 仅使用一个命名索引来查找表中的行。替代语法 IGNORE INDEX (index_list) 可用于告诉 MySQL 不要使用某些特定的索引或索引。如果 EXPLAIN 显示 MySQL 使用了可能索引列表中的错误索引,这些提示将很有用。

您还可以使用 FORCE INDEX,它的作用类似于 USE INDEX (index_list),但另外假设表扫描的开销非常大。换句话说,仅当无法使用给定索引之一来查找表中的行时才使用表扫描。

更新

试试这个查询:

SELECT exec_date, 
       100 * SUM(IF(cached = 0, 1, 0)) / SUM(1) cached_no, 
       100 * SUM(IF(cached = 1, 1, 0)) / SUM(1) cached_yes 
FROM (SELECT exec_date, IF(cached = 'no', 0, 1) cached 
      FROM requests GROUP BY exec_date) AS A 

关于mysql - 创建索引的顺序会影响查询优化器将选择哪个索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13559610/

相关文章:

mysql - Rails无法使用mysql生成模型

mysql - 查询以根据MySQL中的第1列选择第2列中的重复项

php - MySQL从多个表中复制SELECT中的数据

php - laravel 查询 mysql 等效项

mysql - Solr DataImportHandler 外部表

php - 使用大型数据库时,Ajax 请求需要很长时间才能完成

php - 处理多个表单输入字段

mysql - 在 MySQL 的同一查询中使用别名

java - 从数据库中选取数据时的动态 ListView 或 TextView

php - 在预先存在的 JSON 对象中和给定的 json 对象索引之后添加空 json 对象 - Php