MySQL warm procedure
If you would like to warm your MyISAM Key Buffer you could run this:
SELECT DISTINCT CONCAT('SELECT ',ndxcollist,' FROM ',db,'.',tb,' ORDER
BY ',ndxcollist,';') SelectQueryToLoadCache
FROM (SELECT engine,table_schema db,table_name tb,index_name,
GROUP_CONCAT(column_name ORDER BY seq_in_index) ndxcollist
FROM (SELECT
B.engine,A.table_schema,A.table_name,A.index_name,A.column_name,A.seq_in_index
FROM information_schema.statistics A INNER JOIN
(SELECT engine,table_schema,table_name
FROM information_schema.tables
WHERE engine='MyISAM' AND table_schema
NOT IN ('information_schema','mysql')) B
USING (table_schema,table_name)
WHERE A.index_type <> 'FULLTEXT'
ORDER BY table_schema,table_name,index_name,seq_in_index) A
GROUP BY table_schema,table_name,index_name) AA
ORDER BY db,tb
;
Here is the output:
+----------------------------------------------------------------------+
| SelectQueryToLoadCache |
+----------------------------------------------------------------------+
| SELECT start_time FROM annarbor.sq_20110722 ORDER BY start_time; |
| SELECT id FROM junk.category ORDER BY id; |
| SELECT id FROM junk.mytabletolimit ORDER BY id; |
| SELECT parent_id FROM junk.observations ORDER BY parent_id; |
| SELECT id FROM junk.observations ORDER BY id; |
| SELECT parent_id FROM junk.pctable ORDER BY parent_id; |
| SELECT id FROM junk.pctable ORDER BY id; |
| SELECT id FROM junk.products ORDER BY id; |
| SELECT id FROM junk.subcategory ORDER BY id; |
| SELECT id FROM test.acties ORDER BY id; |
| SELECT id FROM test.deletekeys ORDER BY id; |
| SELECT email FROM test.emailtable ORDER BY email; |
| SELECT id FROM test.emailtable ORDER BY id; |
| SELECT id FROM test.ft_test ORDER BY id; |
| SELECT id_key FROM test.id_key_table ORDER BY id_key; |
| SELECT id_key FROM test.id_key_table_keys ORDER BY id_key; |
| SELECT id FROM test.mytabletodeletefrom ORDER BY id; |
| SELECT NGRAM_ID FROM test.ngram_key ORDER BY NGRAM_ID; |
| SELECT NGRAM FROM test.ngram_key ORDER BY NGRAM; |
| SELECT NGRAM_ID FROM test.ngram_rec ORDER BY NGRAM_ID; |
| SELECT num FROM test.notforeverdata_matches ORDER BY num; |
| SELECT id FROM test.pamela ORDER BY id; |
| SELECT id FROM test.rolando ORDER BY id; |
| SELECT num FROM test.rolando2 ORDER BY num; |
| SELECT CourseName FROM test.tab ORDER BY CourseName; |
| SELECT CourseName FROM test.tab_to_zap ORDER BY CourseName; |
| SELECT academy FROM test.under99color ORDER BY academy; |
| SELECT id FROM test.under99color ORDER BY id; |
| SELECT id_key FROM test.weekly_batch ORDER BY id_key; |
| SELECT id FROM test.worktable ORDER BY id; |
+----------------------------------------------------------------------+
30 rows in set (0.81 sec)
mysql>
This displays every possible query you could run against MyISAM tables selecting index column fields only. Running those queries will populate the MyISAM Key Buffer.
Here is a similar query to make queries that preload the InnoDB Buffer Pool
SELECT DISTINCT
CONCAT('SELECT ',ndxcollist,' FROM ',db,'.',tb,
' ORDER BY ',ndxcollist,';') SelectQueryToLoadCache
FROM
(
SELECT
engine,table_schema db,table_name tb,
index_name,GROUP_CONCAT(column_name ORDER BY seq_in_index) ndxcollist
FROM
(
SELECT
B.engine,A.table_schema,A.table_name,
A.index_name,A.column_name,A.seq_in_index
FROM
information_schema.statistics A INNER JOIN
(
SELECT engine,table_schema,table_name
FROM information_schema.tables WHERE
engine='InnoDB'
) B USING (table_schema,table_name)
WHERE B.table_schema NOT IN ('information_schema','mysql')
ORDER BY table_schema,table_name,index_name,seq_in_index
) A
GROUP BY table_schema,table_name,index_name
) AA
ORDER BY db,tb
;
Here is a similar query to make queries that preload the InnoDB Buffer Pool and the MyISAM Key Buffer (I posted this back in November 2011)
SELECT DISTINCT
CONCAT('SELECT ',ndxcollist,' FROM ',
db,'.',tb,' ORDER BY ',ndxcollist,';') SelectQueryToLoadCache
FROM (
SELECT
engine,table_schema db,table_name tb,index_name,
GROUP_CONCAT(column_name ORDER BY seq_in_index) ndxcollist
FROM (
SELECT
B.engine,A.table_schema,A.table_name,
A.index_name,A.column_name,A.seq_in_index
FROM
information_schema.statistics A INNER JOIN
(
SELECT engine,table_schema,table_name
FROM information_schema.tables
WHERE engine IN ('InnoDB','MyISAM')
) B USING (table_schema,table_name)
WHERE
B.table_schema NOT IN ('information_schema','mysql')
AND A.index_type <> 'FULLTEXT'
ORDER BY
table_schema,table_name,index_name,seq_in_index
) A
GROUP BY
table_schema,table_name,index_name
) AA
ORDER BY
engine DESC,db,tb
;
If you see the same query appear more than once in a display, this indicates the presence of redundant indexes.
Give it a Try !!!
UPDATE 2012-02-04 21:53 EDT
While one can create caches dedicated to MyISAM via as follows:
SET GLOBAL authentication_cache.key_buffer_size = 1024 * 1024 * 8;
CACHE INDEX mydb.users INTO authentication_cache;
LOAD INDEX INTO CACHE mydb.users;
you must still decide to load all indexes or specific ones. The script I provided simply shows you the list of all possible indexes you can load. You are not obligated to load all indexes, just the ones you know are used the most. If you have the hardware and budget, you load as much as you like into the dedicated MyISAM caches.
Here is something else to consider: All the queries mentioned are actually accessing covering indexes. Running those queries will only access the MyISAM pages of the .MYI file and only the index pages of an InnoDB tables. Table data is never retrieved. In light of this, all or selected queries populated index pages regardless of storage engine.
More Links on the Principles of Covering Indexes
- http://www.mysqlperformanceblog.com/2006/11/23/covering-index-and-prefix-indexes/
- http://ronaldbradford.com/blog/tag/covering-index/
- http://shallop.com/2011/04/covering-indexes-in-mysql/
- http://www.mysqlconf.com/mysql2009/public/schedule/detail/6796
UPDATE 2012-02-04 22:05 EDT
Quick note about InnoDB vs MyISAM. You can cache data pages for InnoDB. MyISAM no.
If you're running a sufficiently recent version of percona's server you can make use of their innodb_auto_lru_dump config option. This is only relevant for innodb tables/dbs.
It will basically maintain a map file of pages to be reloaded into the buffer pool on start up before it starts accepting connections.
On a dedicated server w/ 144 GB of buffer pool it maintained a 71M map file of pages to reload. It added 5 minutes to the startup time (but is on fusionio). I've had similar startup times on remote boxes that only have a couple gigs of buffer pool but crummy disks.