使用索引优化MySQL查询(什么索引?)
我正在努力优化以下查询,平均需要2000毫秒使用索引优化MySQL查询(什么索引?),mysql,performance,Mysql,Performance,我正在努力优化以下查询,平均需要2000毫秒 select count(pk) from mytable where (pk<>5 and url='test.png' and (data=124578 or (data is null and pk=1234578))) and type in (123,456,789,015,789) 1 526 588条线路 show indexes in mytable
select count(pk)
from mytable
where (pk<>5
and url='test.png'
and (data=124578 or (data is null and pk=1234578)))
and type in (123,456,789,015,789)
1 526 588条线路
show indexes in mytable
Table non_unique key_name seq_in_index column_name collation cardinality
mytable 0 PRIMARY 1 PK A 1405079
mytable 1 data 1 data A 1405079
mytable 1 Media_Code_30 1 code A 1405079
mytable 1 codeVersionIDX_30 1 code A 1405079
说明:
id select_type table type possible_keys key key_len ref rows extra
1 SIMPLE mytable ref_or_null PRIMARY,data data 9 const 635908 Using where
我真的不知道这是否足够优化,或者通过创建新索引(或复合索引)可以更好
但是,无法更改该查询,因为它来自另一个系统,而我不在该系统上 Hmmm,此查询似乎很难为以下内容设置索引:
select count(pk)
from mytable
where (pk <> 5 and url = 'test.png' and
(data = 124578 or (data is null and pk = 1234578))
) and
type in (123, 456, 789, 015, 789);
选择计数(主键)
从mytable
其中(pk 5和url='test.png'和
(数据=124578或(数据为空且pk=1234578))
)及
输入(123、456、789、015、789);
我的建议是从
type
开始,并在索引中包括其他列:mytable(type、url、data、pk)
。这是一个覆盖索引,可能会稍微提高性能。Hmmm,此查询似乎很难为以下内容设置索引:
select count(pk)
from mytable
where (pk <> 5 and url = 'test.png' and
(data = 124578 or (data is null and pk = 1234578))
) and
type in (123, 456, 789, 015, 789);
选择计数(主键)
从mytable
其中(pk 5和url='test.png'和
(数据=124578或(数据为空且pk=1234578))
)及
输入(123、456、789、015、789);
我的建议是从
type
开始,并在索引中包括其他列:mytable(type、url、data、pk)
。这是一个覆盖索引,可能会稍微提高性能。MySQL在一个查询中只能使用一个索引
因此,有必要建立综合指数。索引中字段顺序的最佳方法是字段,它可以最大程度地减少结果集,等等
假设你有一张有名字和生日的桌子,你有许多重复的名字,只有很少的生日。然后创建索引,比如(生日,名字)mysql搜索,首先搜索当天的记录,然后在这个小结果中,名字只能在一个查询中使用一个索引 因此,有必要建立综合指数。索引中字段顺序的最佳方法是字段,它可以最大程度地减少结果集,等等
假设你有一张有名字和生日的桌子,你有许多重复的名字,只有很少的生日。然后创建索引,比如(生日、名称)mysql搜索,首先搜索当天的记录,然后只在这个小结果中搜索名称,这不是答案。只有一些用于使用索引的示例 样本
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500 AND num2 = 600;
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
| 1 | SIMPLE | useindex | index_merge | n1,n2 | n2,n1 | 5,5 | NULL | 1 | Using intersect(n2,n1); Using where; Using index |
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
1 row in set (0.00 sec)
MariaDB [bb]>
小桌子
MariaDB [bb]> SHOW CREATE TABLE useindex\G
*************************** 1. row ***************************
Table: useindex
Create Table: CREATE TABLE `useindex` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`num1` int(11) DEFAULT NULL,
`num2` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2031586 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
MariaDB [bb]> ALTER TABLE useindex
-> ADD KEY n1 (num1),
-> ADD KEY n2 (num2);
Query OK, 0 rows affected (12.08 sec)
Records: 0 Duplicates: 0 Warnings: 0
行数和样本数据
MariaDB [bb]> SELECT count(*) FROM USEindex;
+----------+
| count(*) |
+----------+
| 2000000 |
+----------+
1 row in set (0.43 sec)
MariaDB [bb]> SELECT * FROM useindex LIMIT 10;
+----+------+------+
| id | num1 | num2 |
+----+------+------+
| 1 | 405 | 906 |
| 2 | 656 | 656 |
| 3 | 906 | 407 |
| 4 | 156 | 157 |
| 5 | 406 | 908 |
| 6 | 656 | 659 |
| 7 | 907 | 409 |
| 8 | 157 | 160 |
| 9 | 407 | 910 |
| 10 | 657 | 661 |
+----+------+------+
10 rows in set (0.00 sec)
解释3个查询(无索引)
添加2个索引
MariaDB [bb]> SHOW CREATE TABLE useindex\G
*************************** 1. row ***************************
Table: useindex
Create Table: CREATE TABLE `useindex` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`num1` int(11) DEFAULT NULL,
`num2` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2031586 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
MariaDB [bb]> ALTER TABLE useindex
-> ADD KEY n1 (num1),
-> ADD KEY n2 (num2);
Query OK, 0 rows affected (12.08 sec)
Records: 0 Duplicates: 0 Warnings: 0
用索引解释
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500;
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | useindex | ALL | NULL | NULL | NULL | NULL | 1996444 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num2 = 600;
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | useindex | ALL | NULL | NULL | NULL | NULL | 1996444 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500 AND num2 = 600;
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | useindex | ALL | NULL | NULL | NULL | NULL | 1996444 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
查看带有2个字段的WHERE,MySQL是否只使用一个索引
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500;
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| 1 | SIMPLE | useindex | ref | n1 | n1 | 5 | const | 2003 | |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num2 = 600;
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| 1 | SIMPLE | useindex | ref | n2 | n2 | 5 | const | 1993 | |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500 AND num2 = 600;
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | useindex | ref | n1,n2 | n2 | 5 | const | 1993 | Using where |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
1 row in set (0.00 sec)
在两个字段上添加综合索引
MariaDB [bb]> ALTER TABLE useindex
-> ADD KEY n12 (num1,num2);
Query OK, 0 rows affected (7.83 sec)
Records: 0 Duplicates: 0 Warnings: 0
再次解释查询
现在,他们使用共站点索引
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500;
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | useindex | ref | n1,n12 | n12 | 5 | const | 2003 | Using index |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num2 = 600;
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| 1 | SIMPLE | useindex | ref | n2 | n2 | 5 | const | 1993 | |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500 AND num2 = 600;
+------+-------------+----------+------+---------------+------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------------+------+-------------+
| 1 | SIMPLE | useindex | ref | n1,n2,n12 | n12 | 10 | const,const | 1 | Using index |
+------+-------------+----------+------+---------------+------+---------+-------------+------+-------------+
1 row in set (0.00 sec)
告诉优化器合并索引
MariaDB [bb]> SET optimizer_switch='index_merge=on';
Query OK, 0 rows affected (0.00 sec)
下跌指数n12
MariaDB [bb]> alter table useindex drop key n12;
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0
使用MERGE运行一个查询
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500 AND num2 = 600;
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
| 1 | SIMPLE | useindex | index_merge | n1,n2 | n2,n1 | 5,5 | NULL | 1 | Using intersect(n2,n1); Using where; Using index |
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
1 row in set (0.00 sec)
MariaDB [bb]>
这不是答案。只有一些用于使用索引的示例 样本
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500 AND num2 = 600;
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
| 1 | SIMPLE | useindex | index_merge | n1,n2 | n2,n1 | 5,5 | NULL | 1 | Using intersect(n2,n1); Using where; Using index |
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
1 row in set (0.00 sec)
MariaDB [bb]>
小桌子
MariaDB [bb]> SHOW CREATE TABLE useindex\G
*************************** 1. row ***************************
Table: useindex
Create Table: CREATE TABLE `useindex` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`num1` int(11) DEFAULT NULL,
`num2` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2031586 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
MariaDB [bb]> ALTER TABLE useindex
-> ADD KEY n1 (num1),
-> ADD KEY n2 (num2);
Query OK, 0 rows affected (12.08 sec)
Records: 0 Duplicates: 0 Warnings: 0
行数和样本数据
MariaDB [bb]> SELECT count(*) FROM USEindex;
+----------+
| count(*) |
+----------+
| 2000000 |
+----------+
1 row in set (0.43 sec)
MariaDB [bb]> SELECT * FROM useindex LIMIT 10;
+----+------+------+
| id | num1 | num2 |
+----+------+------+
| 1 | 405 | 906 |
| 2 | 656 | 656 |
| 3 | 906 | 407 |
| 4 | 156 | 157 |
| 5 | 406 | 908 |
| 6 | 656 | 659 |
| 7 | 907 | 409 |
| 8 | 157 | 160 |
| 9 | 407 | 910 |
| 10 | 657 | 661 |
+----+------+------+
10 rows in set (0.00 sec)
解释3个查询(无索引)
添加2个索引
MariaDB [bb]> SHOW CREATE TABLE useindex\G
*************************** 1. row ***************************
Table: useindex
Create Table: CREATE TABLE `useindex` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`num1` int(11) DEFAULT NULL,
`num2` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2031586 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
MariaDB [bb]> ALTER TABLE useindex
-> ADD KEY n1 (num1),
-> ADD KEY n2 (num2);
Query OK, 0 rows affected (12.08 sec)
Records: 0 Duplicates: 0 Warnings: 0
用索引解释
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500;
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | useindex | ALL | NULL | NULL | NULL | NULL | 1996444 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num2 = 600;
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | useindex | ALL | NULL | NULL | NULL | NULL | 1996444 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500 AND num2 = 600;
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | useindex | ALL | NULL | NULL | NULL | NULL | 1996444 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
查看带有2个字段的WHERE,MySQL是否只使用一个索引
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500;
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| 1 | SIMPLE | useindex | ref | n1 | n1 | 5 | const | 2003 | |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num2 = 600;
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| 1 | SIMPLE | useindex | ref | n2 | n2 | 5 | const | 1993 | |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500 AND num2 = 600;
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | useindex | ref | n1,n2 | n2 | 5 | const | 1993 | Using where |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
1 row in set (0.00 sec)
在两个字段上添加综合索引
MariaDB [bb]> ALTER TABLE useindex
-> ADD KEY n12 (num1,num2);
Query OK, 0 rows affected (7.83 sec)
Records: 0 Duplicates: 0 Warnings: 0
再次解释查询
现在,他们使用共站点索引
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500;
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | useindex | ref | n1,n12 | n12 | 5 | const | 2003 | Using index |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num2 = 600;
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
| 1 | SIMPLE | useindex | ref | n2 | n2 | 5 | const | 1993 | |
+------+-------------+----------+------+---------------+------+---------+-------+------+-------+
1 row in set (0.00 sec)
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500 AND num2 = 600;
+------+-------------+----------+------+---------------+------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+-------------+------+-------------+
| 1 | SIMPLE | useindex | ref | n1,n2,n12 | n12 | 10 | const,const | 1 | Using index |
+------+-------------+----------+------+---------------+------+---------+-------------+------+-------------+
1 row in set (0.00 sec)
告诉优化器合并索引
MariaDB [bb]> SET optimizer_switch='index_merge=on';
Query OK, 0 rows affected (0.00 sec)
下跌指数n12
MariaDB [bb]> alter table useindex drop key n12;
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0
使用MERGE运行一个查询
MariaDB [bb]> EXPLAIN SELECT * FROM useindex WHERE num1 = 500 AND num2 = 600;
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
| 1 | SIMPLE | useindex | index_merge | n1,n2 | n2,n1 | 5,5 | NULL | 1 | Using intersect(n2,n1); Using where; Using index |
+------+-------------+----------+-------------+---------------+-------+---------+------+------+--------------------------------------------------+
1 row in set (0.00 sec)
MariaDB [bb]>
该查询的最佳索引是
INDEX(url, type) -- in that order
索引应该以“=constant”的任何列开始(在本例中为“
url
”),然后再移动到一个更复杂的列(键入…
) 该查询的最佳索引是
INDEX(url, type) -- in that order
索引应该以“=constant”的任何列开始(在本例中为“
url
”),然后再移动到一个更复杂的列(键入…
) 什么时候MySQL可以在一个查询中只使用一个索引?有文件支持吗?我愿意相信你。20年来,我一直在谈论子查询。问一个问题,看看埃普兰说了什么。优化器查找可用索引并使用最佳索引或无索引,或者更新meSo没有说明“MySQL每个查询仅使用一个索引”的文档,或者我误解了您的意思,您的意思是“在OP发布的查询中,MySQL只能使用一个索引”?抱歉,我可以快速找到包含此信息的文档,但我也没有发现mysql可以使用更多。但我会在稍后搜索并发布一个链接。实际上,使用两个索引是非常罕见的,不值得考虑。MySQL对单个SELECT
使用两个索引的唯一方法是从两个索引中的每一个获取ID,然后在某个临时空间中对列表进行“anding”(“intersect”)或“oring”(“union”)操作。所有这些都是庞大而缓慢的,因此很少能比简单地使用一个索引,然后在WHERE
或(在连接
的情况下,使用嵌套循环连接)上进行过滤来提高性能?有文件支持吗?我愿意相信你。20年来,我一直在谈论子查询。问一个问题,看看埃普兰说了什么。优化器查找可用索引并使用最佳索引或无索引,或者更新meSo没有说明“MySQL每个查询仅使用一个索引”的文档,或者我误解了您的意思,您的意思是“在OP发布的查询中,MySQL只能使用一个索引”?抱歉,我可以快速找到包含此信息的文档,但我也没有发现mysql可以使用更多。但我会在稍后搜索并发布一个链接。实际上,使用两个索引是非常罕见的,不值得考虑。MySQL对单个SELECT
使用两个索引的唯一方法是从两个索引中的每一个获取ID,t