【问题标题】:Does order of columns of Multi-Column Indexes in where clause in MySQL matter?MySQL where 子句中多列索引的列顺序是否重要?
【发布时间】:2017-12-19 09:21:35
【问题描述】:

我有一张下表:

CREATE TABLE `student` ( 
     `name` varchar(30) NOT NULL DEFAULT '',
     `city` varchar(30) NOT NULL DEFAULT '', 
     `age`  int(11) NOT NULL DEFAULT '0',
     PRIMARY KEY (`name`,`city`) 
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我想知道,如果我执行以下两条SQL,它们的性能是否相同?

mysql> select * from student where name='John' and city='NewYork';
mysql> select * from student where city='NewYork' and name='John';

涉及的问题:

  1. 如果有一个多列索引(name、city),两个sql都用吗?
  2. 优化器会不会因为索引把第二条sql改成第一条?

我对他们两个执行解释,结果如下:

mysql> explain select * from student where name='John' and city='NewYork';
+----+-------------+---------+-------+---------------+---------+---------+-------------+------+-------+

| id | select_type | table   | type  | possible_keys | key     | key_len | ref         | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------------+------+-------+

|  1 | SIMPLE      | student | const | PRIMARY       | PRIMARY | 184     | const,const |    1 | NULL  |
+----+-------------+---------+-------+---------------+---------+---------+-------------+------+-------+

mysql> 解释 select * from student where city='NewYork' and name='John';

+----+-------------+---------+-------+---------------+---------+---------+-------------+------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref         | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------------+------+-------+

|  1 | SIMPLE      | student | const | PRIMARY       | PRIMARY | 184     | const,const |    1 | NULL  |
+----+-------------+---------+-------+---------------+---------+---------+-------------+------+-------+

【问题讨论】:

  • 多列索引中的列顺序很重要。可以使用列namecity 上的索引来代替列name 上的索引,但不能使用它来代替列city 上的索引。 WHERE 子句中的条件顺序无关紧要。
  • 欢迎来到 Stack Overflow。你问的第一个问题做得很好。

标签: mysql sql indexing query-performance


【解决方案1】:

如果给定(name,city)上的索引,我执行以下两条SQL,它们的性能是否相同?

where name='John' and city='NewYork'

where city='NewYork' and name='John'

是的。

查询规划器不关心WHERE 子句的顺序。如果您的两个子句都过滤相等,则规划器可以使用索引。 SQL 是一种声明性 语言,而不是过程性语言。 也就是说,你说你想要什么,而不是如何得到它。 em> 这对许多程序员来说有点违反直觉。

它还可以将(name,city) 索引用于WHERE name LIKE 'Raymo%',因为name 在索引中是第一个。但是,它不能将该索引用于WHERE city = 'Kalamazoo'

它可以使用WHERE city LIKE 'Kalam%' AND name = 'Raymond' 的索引。在这种情况下,它使用索引来查找名称值,然后扫描匹配的城市。

如果您在(city,name) 上有一个索引,您也可以将它用于WHERE city = 'Kalamazoo' AND name = 'Raymond'。如果两个索引都存在,查询规划器将选择一个,可能基于某种基数考虑。

注意。相反,如果您在 cityname 上有两个不同的索引,则查询规划器(截至 2017 年年中)不能使用多个索引来满足 WHERE city = 'Kalamazoo' AND name = 'Raymond'

http://use-the-index-luke.com/ 了解更多信息。

【讨论】:

    【解决方案2】:

    多列索引中的列顺序很重要。

    multiple-column indexes 的文档内容如下:

    MySQL 可以将多列索引用于测试索引中所有列的查询,或者只测试第一列、前两列、前三列等的查询。如果您在索引定义中以正确的顺序指定列,则单个复合索引可以加快对同一张表的多种查询。

    这意味着当需要列name 的索引但不能使用列city 的索引时,可以使用列namecity 的索引。

    WHERE 子句中的条件顺序无关紧要。 MySQL 优化器does a lot of workWHERE 子句上的条件下,尽可能早地消除候选行,并从表和索引中读取尽可能少的数据(因为删除了一些读取的数据,因为它与整个 WHERE 子句不匹配)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-10
      • 2012-07-11
      • 2015-04-13
      • 2011-03-05
      • 2011-01-18
      • 1970-01-01
      相关资源
      最近更新 更多