Multi-Column Index Behavior in MySQL with Unused Index Column - mysql

Suppose I define the following index on a table in a MySQL database:
(col1, col2, col3)
I know that I get indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3).
Do I also get indexed search capabilities on (col1, col3)?

This is my experience with MSSQL so please test with MySQL
Consider a composite index on (col1, col2, col3)
You get an index seek on:
col1
col1 & col2
col1 & col2 & col3
On col2 and col3 you can get an index (not table) scan.
Since the index is smaller than the table this can help search times.
Some times this is a significant impact.
A search on col1 and col3 would (hopefully) be an index seek on col1 and an index scan on col3.
And note if the table is small you will just get some default plans
Need to load up with some data to test

Summing up Marc B's answers from the comments:
You do not get full indexed search capabilities on (col1, col3) from the index (col1, col2, col3); however, you will still get the benefits of a (col1) index with indexed search capabilities from the first level match on the col1 portion of the query. A table scan would then be used on col3.
If it is necessary to have full indexed search capabilities on (col1, col3) (it may not be - see Eugen Rieck's comment), you would need a separate index on (col1, col3).

Related

Optimize a SQL query with INDEX

I have a very simple query
SELECT col1, col2, col3, col4 FROM table FORCE INDEX (col2)
WHERE col2 IN ('there', 'are, 'around', 'six', 'values', 'here')
with index col2 for col2. My table has around 10 millions row. I used FORCE INDEX here because there are other indices in my table and MySQL uses one of other indices instead of index col2. The other index is very slow for this query.
List of all indices in my table:
INDEX col2 (col2)
UNIQUE INDEX ind1 (col1, col2)
INDEX ind2 (col1, col2)
INDEX ind3 (col2, col1)
This query (with FORCE INDEX) is not slow (takes 6 seconds on AWS RDS free tier) but there is a need to make it as fast as possible. Is there any thing else I could do to speed up this query?
First, you should try not forcing the index on col2, and instead just look at the explain plan. It is likely that a single column index on col2 would be used here. However, you can try adding the following composite covering index on your table:
CREATE INDEX idx ON yourTable (col2, col1, col3, col4);
This index would cover the WHERE clause, and also includes the other columns which appear in the SELECT clause. If it chooses, MySQL could use this index to completely cover the entire query without needing to seek back to the clustered index (i.e. the original table).
INDEX col2 (col2)
UNIQUE INDEX ind1 (col1, col2)
INDEX ind2 (col1, col2)
INDEX ind3 (col2, col1)
Some of these indexes are redundant. MySQL can use (col2, col1) for searches on col2 as well as searches on both col2 and col1. And ind2 is fully redundant with ind1.
The redundancy might be confusing the optimizer.
To cover all combinations of col1 and col2, as well as enforce uniqueness, you only need...
INDEX col2 (col2)
UNIQUE INDEX ind1 (col1, col2)
Removing the redundant indexes will speed up inserts and save space.
See 8.3.6 Multiple-Column Indexes.
The query planner makes its guesses based on table statistics. Sometimes those statistics are out of date. Try running analyze table to update them.

How to create Multiple-Column Indexes efficiently?

Let's say I've coded.
create index use_index on tbl_nm (col2 ,col3 ,col4 ,col5);
would use_index be used in
select * from tbl_nm where col2="something", col5 = "something", col3="something");
Also, we should have created index by ordering the most unique on the left and the most common on the right. right?
And if I would like to order the query result should I add that column into the index too?
The index should be at least refs used in common queries first followed by columns search by range.
So in your example here col2 and col3 will be use this index. but because there is no col4, the searching for col5 won't be as quick. i.e. all col4 items with col2 and col3 matching "something" will be scanned for a matching col5.
If you where searching for col4 rather than col5, it would be a binary search to the required item.
Use EXPLAIN {query} to show what the index usage is.
Consideration of most unique vs least in the order of the index isn't really considered.

Do MySQL complex indexes involve simple indexes?

If I set a multi-column index -unique for example- with columns (A, B) and search by A or B independently, will they be as fast as if I also have simple indexes in A and B?
Are those extra simple indexes necessary?
From MYSQL:MySQl 5 Reference
If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to find rows. For example, if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3).
MySQL cannot use an index if the columns do not form a leftmost prefix of the index. Suppose that you have the SELECT statements shown here:
SELECT * FROM tbl_name WHERE col1=val1;
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
SELECT * FROM tbl_name WHERE col2=val2;
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
If an index exists on (col1, col2, col3), only the first two queries use the index. The third and fourth queries do involve indexed columns, but (col2) and (col2, col3) are not leftmost prefixes of (col1, col2, col3).
If you create any index that is (A,B), MySQL can utilize that index for queries and sorts that have just A, or A then B. It can not use it for "B". The basic idea is that any prefix of the index is useful.
You don't have to create a separate one for "A", but you would need one for "B" if B was going to be sorted on or used in a where clause without "A".

MySQL Unnecessary Indexes

If I have this index:
(col1, col2, col3)
I know it helps when I search through (col1); (col1, col2); (col1, col2, col3).
If I create another index with the exactly same columns, phpMyAdmin will warn me that one of those indexes may be removed, because they are the same.
However, if I have these indexes:
(col1, col2, col3)
(col1, col2)
(col1)
phpMyAdmin won't warn me at all.
So my question is, are the last two indexes necessary in any case? I think only the first index is enough.
Thank you.
MySQL will only use one index (the leftmost) to optimize the search. Quoting from the documentation:
"If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to find rows. For example, if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3)."
However, if any of the indexes are UNIQUE, then there's probably a good reason for them to be there.
If during your analysis you find that any of the columns are frequently used apart from one another, then you should consider adding separate indexes for each to optimize those queries.
E.g.
ALTER TABLE tablename ADD INDEX (col1), ADD INDEX (col2), ADD INDEX (col3);

What happens if I drop a MySQL column without dropping its index first?

With one of my MySQL tables, I dropped column col1 before I drop it from a unique index (col0, col1, col2, col3) that contains it.
Is it automatically taken care of by MySQL? It seems the unique index that was previously (col0, col1, col2, col3) was automatically changed to (col0, col2, col3) after I deleted the column col1.
Is it going to be a problem or do I have to drop the unique index and re-create it as (col0, col2, col3)?
According to the MySQL 5.1 Reference Manual:
If columns are dropped from a table,
the columns are also removed from any
index of which they are a part. If all
columns that make up an index are
dropped, the index is dropped as well.
If you use CHANGE or MODIFY to shorten
a column for which an index exists on
the column, and the resulting column
length is less than the index length,
MySQL shortens the index
automatically.