我正在努力优化以下查询,平均需要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)
以下是一些信息:
select count(*) from mytable
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
我真的不知道这是否足够优化,或者通过创建新索引(或复合索引)可以更好。
然而,查询无法更改,因为它来自另一个我没有动手的系统!
答案 0 :(得分:2)
嗯,这个查询似乎很难设置索引:
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);
我的建议是从type
开始,并在索引中包含其他列:mytable(type, url, data, pk)
。这是一个覆盖索引,可能会稍微提高性能。
答案 1 :(得分: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]> 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)
EXPLAIN 3查询(无索引)
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个索引
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
使用索引进行分析
看看WHERE有2个字段,MySQL只使用一个INDEX
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)
在两个字段上添加COMPOSITE索引
MariaDB [bb]> ALTER TABLE useindex
-> ADD KEY n12 (num1,num2);
Query OK, 0 rows affected (7.83 sec)
Records: 0 Duplicates: 0 Warnings: 0
再次EXPLAIN查询
现在他们使用COMOSITE索引
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)
告诉OPTIMIZER合并指数
MariaDB [bb]> SET optimizer_switch='index_merge=on';
Query OK, 0 rows affected (0.00 sec)
删除INDEX n12
MariaDB [bb]> alter table useindex drop key n12;
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0
使用MERGE运行一个QUERY
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]>
答案 2 :(得分:0)
MySQL只能在查询中使用一个INDEX。
所以有必要有复合索引。索引中字段顺序的最佳方式是主要减少结果集的字段,依此类推。
假设你有一张名字和生日的桌子,你有许多重复的名字,只有几个生日。所以然后创建索引像(生日,名字)mysql搜索首先记录搜索日,然后只在这个小结果名称
答案 3 :(得分:0)
该查询的最佳索引是
INDEX(url, type) -- in that order
索引应该以&#34; =常量&#34;的任何列开头。 (在这种情况下为url
),然后再转到另一个更复杂的列(type IN ...
)。 See my cookbook