dot*_*hen 0 mysql optimization explain
我在AWS RDS 中型实例上有一个大型 MySQL 数据库表(约 100 万行并且还在增长):
mysql> describe clients;
+-----------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(500) | YES | | NULL | |
| address | varchar(500) | YES | | NULL | |
| city | varchar(200) | YES | | NULL | |
| state | varchar(100) | YES | | NULL | |
| zip | varchar(50) | YES | | NULL | |
| country | varchar(50) | YES | | NULL | |
| phone | varchar(20) | YES | UNI | NULL | |
| source | varchar(20) | YES | MUL | NULL | |
| campaign | varchar(200) | YES | | NULL | |
| search_term | varchar(200) | YES | | NULL | |
| search_location | varchar(200) | YES | | NULL | |
| added | datetime | YES | | NULL | |
| email | varchar(150) | YES | | NULL | |
| website | varchar(150) | YES | | NULL | |
| full_output | varchar(5000) | YES | | NULL | |
| client | varchar(50) | YES | | NULL | |
| is_deleted | int(2) | YES | | 0 | |
| is_valid | int(2) | YES | | 1 | |
+-----------------+---------------+------+-----+---------+----------------+
19 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
我经常需要执行以下查询的变体:
SELECT name, zip FROM clients WHERE source IN ('Foo','foo','Bar','bar') AND added>'2013-11-25 13:00:00' limit 150000, 150000;
Run Code Online (Sandbox Code Playgroud)
和相关的EXPLAIN
:
mysql> EXPLAIN SELECT name, zip FROM clients WHERE source IN ('Foo','foo','Bar','bar') AND added>'2013-11-25 13:00:00' limit 150000, 150000;
+----+-------------+------------+-------+---------------+--------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+--------+---------+------+---------+-------------+
| 1 | SIMPLE | clients | range | source | source | 63 | NULL | 1168144 | Using where |
+----+-------------+------------+-------+---------------+--------+---------+------+---------+-------------+
1 row in set (0.03 sec)
Run Code Online (Sandbox Code Playgroud)
我应该做哪些优化?我应该在name
andzip
字段上添加索引,还是在added
andsource
字段上添加索引?
接受的答案忽略了覆盖索引的概念,也没有提到索引在多个列上的重要性,一起在一个索引中。
WHERE
子句中两列的单个索引:
ALTER TABLE clients ADD KEY(source,added) -- adding this
ALTER TABLE clients ADD KEY(added,source) -- or this
Run Code Online (Sandbox Code Playgroud)
...通常比每列上的单个索引对您的帮助更多,因为否则优化器可能只选择使用两列之一。上述哪个索引更有用取决于“源”和“添加”中值的分布。用于查询的选定索引将出现在EXPLAIN
输出的“key”中。“使用 where”通常意味着,在选择的查询计划将导致获取的行中,服务器意识到其中一些仍然不符合选择标准,并且必须随后由服务器过滤(如在例如,可能需要过滤大量数字,因为没有使用索引)。
一个覆盖索引可能是特别有价值的也是,因为违背了断言,“行内的字段是快速和容易使发动机得到的,”他们只是更快,比发现通过扫描整个表中的行更容易-他们仍然需要时间,并消耗资源。
这就是覆盖索引的用武之地。添加带有 (source, added,zip,name) 的索引可能会大大提高您的性能,因为一旦服务器通过使用索引找到相关行,它就不需要查找其余数据,因为数据实际上在索引内。当使用覆盖索引时,explain 的“key”列将包含正在使用的索引的名称,“Extra”列将包含“using index”(意思是,使用索引实际检索数据,而不仅仅是找到它。)
因此,虽然您确实根据选择标准编制了索引,但这并不是故事的全部。
另请注意,无论索引什么,索引都将仅用于从索引中最左边的列开始的实际搜索,直到遇到不在WHERE
子句中的列。
因此,(source, added) 上的索引可以优化在WHERE
子句中同时包含“源”和“添加”的查询的行的查找......或者子句中只有“源” WHERE
,但该索引不会用于在 where 子句中仅“添加”的查找,因为其左侧有一列未使用。类似地,(source, added,zip,name) 上的单个索引可以优化查询的查询,其中WHERE
子句提到 source ... 或 source and added ... 或 source and added and zip ... 或 source and added and zip and名称......但不仅仅是“zip”......不仅仅是“名称”......不是“添加”和“名称”和“zip”......你明白了。一个索引是不相关的,开始于,在,WHERE
请注意,您在 where 子句中列出事物的顺序没有区别,只要所有条件都是AND
。这是您在网上会发现的一种误解。任何等效的表达式都被优化器理解为等效的。
此外,除非您明确禁用它,否则 IN('Foo','foo') 是多余的,因为由于collations选择将不区分大小写,因此 'foo' 应该足以找到任何大写排列。
归档时间: |
|
查看次数: |
112 次 |
最近记录: |