I'm currently trying to improve the speed of SELECTS for a MySQL table and would appreciate any suggestions on ways to improve it.
We have over 300 million records in the table and the table has the structure tag, date, value. The primary key is a combined key of tag and date. The table contains information for about 600 unique tags most containing an average of about 400,000 rows but can range from 2000 to over 11 million rows.
The queries run against the table are:
SELECT date,
value
FROM table
WHERE tag = "a"
AND date BETWEEN 'x' and 'y'
ORDER BY date
....and there are very few if any INSERTS.
I have tried partitioning the data by tag into various number of partitions but this seems to have little increase in speed.
I think that the
value
column is at the bottom of your performance issues. It is not part of the index so we will have table access. Further I think that the ORDER BY is unlikely to impact the performance so severely since it is part of your index and should be ordered.I will argument my suspicions for the
value
column by the fact that the partitioning does not really reduce the execution time of the query. May you execute the query withoutvalue
and further give us some results as well as the EXPLAIN? Do you really need it for each row and what kind of column is it?Cheers!
I would guess that adding an index on
(tag, date)
would help:Please post the result of an explain on this query (EXPLAIN SELECT date, value FROM ......)
I would do two things - first throw some indexes on there around tag and date as suggested above:
Next break your query into a main query and sub-select in which you are narrowing your results down when you get into your main query:
I'd say your only chance to further improve it is a covering index with all three columns (tag, data, value). That avoids the table access.
I don't think that partitioning can help with that.
take time to read my answer here: (has similar volumes to yours)
500 millions rows, 15 million row range scan in 0.02 seconds.
MySQL and NoSQL: Help me to choose the right one
then amend your table engine to innodb as follows:
you might consider the following as the primary key instead:
but only if value isnt some LARGE varchar type !
query as before:
hope this helps :)
EDIT
oh forgot to mention - dont use alter table to change engine type from mysiam to innodb but rather dump the data out into csv files and re-import into a newly created and empty innodb table.
note i'm ordering the data during the export process - clustered indexes are the KEY !
Export
Import
import back into the table in correct order !
Try inserting just the needed dates into a temporary table and the finishing with a select on the temporary table for the tags and ordering.
if that doesn't work try creating foo off the tag selection instead.