问题描述
|
EXPLAIN SELECT *
FROM (
`PHPpos_items`
)
WHERE (
name LIKE \'AB10LA2%\'
OR item_number LIKE \'AB10LA2%\'
OR category LIKE \'AB10LA2%\'
)
AND deleted =0
ORDER BY `name` ASC
LIMIT 16
+----+-------------+--------------+-------+-----------------------------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+-------+-----------------------------------+------+---------+------+------+-------------+
| 1 | SIMPLE | PHPpos_items | index | item_number,name,category,deleted | name | 257 | NULL | 32 | Using where |
+----+-------------+--------------+-------+-----------------------------------+------+---------+------+------+-------------+
该查询需要9秒钟才能运行(该表有100万以上的行)。
我有关于item_number,name,category的索引,已分别删除。如何加快查询速度?
解决方法
据我所知,MySQL不知道如何执行位图或索引扫描。但是,如果在每个字段上都有索引,则可以将其重写为三个查询的并集,以强制其执行此操作。如果是这样,这将非常快:
select *
from (
select * from (
select *
from phppos_items
where name like \'AB10LA2%\' and deleted = 0
order by `name` limit 16
) t
union
select * from (
select *
from phppos_items
where item_number like \'AB10LA2%\' and deleted = 0
order by `name` limit 16
) t
union
select * from (
select *
from phppos_items
where category like \'AB10LA2%\' and deleted = 0
order by `name` limit 16
) t
) as top rows
order by `name` limit 16
, OR
运算符可能对执行计划有毒。您可以尝试重新表述您的查询,将replacing2ѭ子句替换为等效的UNION
:
SELECT *
FROM (
SELECT * FROM `phppos_items`
WHERE name LIKE \'AB10LA2%\'
UNION
SELECT * FROM `phppos_items`
WHERE item_number LIKE \'AB10LA2%\'
UNION
SELECT * FROM `phppos_items`
WHERE category LIKE \'AB10LA2%\'
)
WHERE deleted =0
ORDER BY `name` ASC
LIMIT 16
这将允许MySQL在将UNION
运算符应用于每个子查询的结果之前,并行运行多个子查询。我知道这对Oracle很有帮助。也许MySQL可以做类似的事情?注意:我假设LIKE \'AB10LA2%\'
是一个选择性过滤器。否则,由于执行计划中的延迟排序和限制,这可能不会改善情况。有关更一般的方法,请参见丹尼斯的答案。
无论如何,我认为多列索引对您没有帮助,因为您的搜索表达式中有8个符号。这样,仅可以使用多列索引中的第一列,其余的仍然需要索引扫描或全表扫描。