Reputation: 7459
I have this table:
+---------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| CODE | varchar(255) | NO | | NULL | |
| REVISION | varchar(255) | NO | | NULL | |
| NAME | varchar(255) | NO | | NULL | |
+---------------------+--------------+------+-----+---------+----------------+
now, my app will perform these queries (from more likely to less likely):
SELECT * FROM ITEM WHERE ID = ?
SELECT * FROM ITEM WHERE CODE = ? ORDER BY REVISION DESC
SELECT * FROM ITEM WHERE CODE = ? AND REVISION = ?
SELECT * FROM ITEM WHERE CODE LIKE ? OR NAME LIKE ? ORDER BY CODE ASC, REVISION DESC
What is the best combination of indexes for such a scenario?
I'm using MySQL 5.6.14 (InnoDB) on Windows 8.1 x64.
UPDATE (still testing):
The best so far is using separate indexes: IDX_CODE (CODE), IDX_NAME (NAME).
mysql> describe select id, code, revision from UNIT where code like 'M0170SIGM1%' or name like 'M0170SIGM1%' ORDER BY code ASC, revision DESC;
+----+-------------+-------+-------------+-------------------+-------------------+---------+------+------+------------------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------------+-------------------+-------------------+---------+------+------+------------------------------------------------------------------+
| 1 | SIMPLE | UNIT | index_merge | IDX_CODE,IDX_NAME | IDX_CODE,IDX_NAME | 767,767 | NULL | 31 | Using sort_union(IDX_CODE,IDX_NAME); Using where; Using filesort |
+----+-------------+-------+-------------+-------------------+-------------------+---------+------+------+------------------------------------------------------------------+
No way to make MySQL use indexes in double direction sorting.
Upvotes: 0
Views: 87
Reputation: 1738
For your fourth case with the mixed asc/desc order it might fail completely to use an index since mysql seems not to support this combination:
Order-By-Optimization in mysql
In some cases, MySQL cannot use indexes to resolve the ORDER BY, although it still uses indexes to find the rows that match the WHERE clause. These cases include the following:
... You mix ASC and DESC: SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
Possible solution for that problem:
if your revision would be simply an positive integer, you could use another column with that value multiplied by -1, and order by this column DESC, which would allow you to use an index on those two columns, since they would have the same direction... works here like a charm with a timestamp column...
Upvotes: 1
Reputation: 1269853
The primary key takes care of the first query.
For the second and third: item(code, revision)
. Note that the order by case asc
is unnecessary because you are only choosing one code.
The last query is problematic. You might want to use a full text index. If the like
attern is does not have a wild card at the beginning, then the following formulation might be better:
select i.*
from (select i.* from item i where code like ? union
select i.* from item i where name like ?
) i
order by code, revision;
However, the engine is probably going to implement this query using full-table scan followed by a sort, regardless of the indexes.
Upvotes: 1