我需要一个多列索引吗?

问题描述

|
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个符号。这样,仅可以使用多列索引中的第一列,其余的仍然需要索引扫描或全表扫描。