See query below. What index should I create on the table so the query will use the index and avoid using temporary and filesort? I've tried many different combinations of indices and read advice here, but I can't seem to figure it out. My explain either says Using Where
(no index), or Using Where Using Temporary, Using Filesort
Here is a simplified query. All columns are Integers.
SELECT c1, Sum(c2)
FROM table
WHERE c3 IS NOT NULL
AND c4 = 2011
AND c5 = 0
AND c6 In (6,9,11)
GROUP BY c1
No, this can be incorrect. If you have a large table, Oracle can prefer deriving the fields from the indexes rather than from the table, even there is no single index that covers all values.
Yes, MySQL uses your index to sort the information when the order is by the sorted column. Also, if you have indexes in all columns that you have added to the SELECT clause, MySQL will not load the data from the table itself, but from the index (which is faster).
The most efficient way to process GROUP BY is when an index is used to directly retrieve the grouping columns. With this access method, MySQL uses the property of some index types that the keys are ordered (for example, BTREE ).
Both GROUP BY and ORDER BY are clauses (or statements) that serve similar functions; that is to sort query results. However, each of these serve very different purposes; so different in fact, that they can be employed separately or together.
This should help you. Rewrite your query as follows:
SELECT c1, Sum(c2)
FROM table
WHERE c4 = 2011
AND c5 = 0
AND c6 In (6,9,11)
AND c3 IS NOT NULL
GROUP BY c1
Now create a composite index on columns (c4, c5, c6) with the columns IN THAT ORDER. The columns in your index should appear in the same order as the columns in your WHERE clause. Otherwise the index will not work. The selectivity of this index is narrow enough that a filesort on the temporary table (for the group by) should be fast.
The reason to move c3 to the end of the query is the following. As an example, let us assume that c3 can take values between 0 and 100 (or it can be NULL). If you run a "IS NOT NULL" query, then Mysql needs to traverse almost all of the B-Tree index except for the edges that correspond to NULL. Therefore, MySQL decides that a full table scan is an easier option than walking through all the different paths in the index. On the other hand, you will see that if your query was an "IS NULL" and your index was (c3, c4, c5, c6) then Mysql will infact use this index. This is because in this case Mysql only needs to traverse the part of the index tree corresponding to the NULL value.
The kind of indexes MySQL needs is very much dependent on the query in question. Creating indexes on all the columns, as @louis suggested, is NOT a good idea!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With