Êý¾Ý¿âµÄÓÅ»¯´ó¸ÅÊÇÔÚϵͳ¹ÜÀíÖÐ×î¾ßÓÐÌôÕ½ÐÔµÄÁË£¬ÒòΪÆä¶ÔÈËÔ±µÄËØÖÊÒªÇ󼸺õÊÇÈ«·½ÃæµÄ£¬ºÃµÄ DBA ÐèÒª¸÷ÖÖ×ÛºÏËØÖÊ¡£ÔÚÅųýÁ˲Ù×÷ϵͳ£¬Ó¦ÓõÈÒýÆðµÄÐÔÄÜÎÊÌâÒÔÍ⣬ÓÅ»¯Êý¾Ý¿â×îºËÐĵÄʵ¼ÊÉϾÍÊÇÅäÖòÎÊýµÄµ÷Õû¡£±¾ÎÄͨ¹ýÒ»¸ö¼òµ¥µÄ²ÎÊýµ÷Õû£¬ÊµÏÖÁ˶ÔÓµÓÐÒ»¸ö¼¸Ê®ÍòÐбíµÄ group by ÓÅ»¯µÄÀý×Ó¡£Í¨¹ýÕâ¸ö¼òµ¥µÄµ÷Õû£¬Êý¾Ý¿âÐÔÄÜÓÐÁËÍ»·ÉÃͽøµÄÌáÉý¡£
±¾Àý×ÓÊÇÕë¶Ô MySQL µ÷ÕûµÄ£¬²»ÏñÆäËûÉÌÒµÊý¾Ý¿â£¬MySQL ûÓÐÊÓͼ£¬ÌرðÊÇ Oracle ¿ÉÒÔÀûÓù̻¯ÊÓͼÀ´ÌáÉý²éѯÐÔÄÜ£¬Ã»Óд洢¹ý³Ì£¬Òò´ËÐÔÄܵĵ÷Õû¼¸ºõÖ»ÄÜͨ¹ýÅäÖúÏÊʵIJÎÊýÀ´ÊµÏÖ¡£
µ÷ÕûµÄ¾ßÌå²½Öè(Àý×ÓÕë¶Ô pLog 0.3x µÄ²©¿Íϵͳ)£º
·¢ÏÖ×î¶àµÄ slow log ÊÇ£º
SELECT category_id, COUNT(*) AS 'count' FROM plog_articles WHERE blog_id = 2 AND status = 'PUBLISHED' group by category_id;
Ò»°ãÔÚ 20s ÒÔÉÏ£¬ÉõÖÁ 30s ¡£
¶øµ± blog_id=1 »òÕßÆäËûʱ£¬¶¼ÄܺܿìµÄÑ¡³ö½á¹û¡£
ÓÚÊÇ»³ÒÉË÷ÒýÓÐÎÊÌ⣬ÖØн¨Á¢Ë÷Òý£¬µ«ÎÞ¼ÃÓÚÊ¡£ EXPLAIN ½á¹ûÈçÏ£º
mysql> EXPLAIN SELECT category_id, COUNT(*) AS 'count' FROM plog_articles WHERE blog_id = 2 AND status = 'PUBLISHED' group by category_id;
+---------------+------+------------------+------------------+---------+-------------+------+----------------------------------------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+---------------+------+------------------+------------------+---------+-------------+------+----------------------------------------------+
| plog_articles | ref | idx_article_blog | idx_article_blog | 5 | const,const | 4064 | Using where; Using temporary; Using filesort |
+---------------+------+------------------+------------------+---------+-------------+------+----------------------------------------------+
1 row in set (0.00 sec)
ÓÚÊÇÏ뵽ÿ´Î²é¿´ blog_id = 2 µÄ²©¿Íʱ£¬ÏµÍ³¸ºÔؾÍÌá¸ß£¬ÓÐ½Ï¸ßµÄ swap ¡£ÓÚÊDz鿴 temporary table ÓйصÄ×ÊÁÏ£¬¹ûÈ»ÓÐÕâÑùµÄ˵·¨£º
If you create a lot of disk-based temporary tables, increase the size of tmp_table_size if you can do so safely. Keep in mind that setting the value too high may result in excessive swapping or MySQL running out of memory if too many threads attempt to allocate in-memory temporary tables at the same time. Otherwise, make sure that tmpdir points to a very fast disk that's not already doing lots of I/O.
Another problem that doesn't show up in the slow query log is an excessive use of disk-based temporary tables. In the output of EXPLAIN, you'll often see Using temporary. It indicates that MySQL must create a temporary table to complete the query. However, it doesn't tell you whether that temporary table will be in memory or on disk. That's controlled by the size of the table and MySQL's tmp_table_size variable.
If the space required to build the temporary table is less than or equal to tmp_table_size, MySQL keeps it in memory rather than incur the overhead and time required to write the data to disk and read it again. However, if the space required exceeds tmp_table_size, MySQL creates a disk-based table in its tmpdir directory (often /tmp on Unix systems.) The default tmp_table_size size is 32 MB.
To find out how often that happens, compare the relative sizes of the Created_tmp_tables and Created_tmp_disk_tables counters:
µ÷Õû tmp_table_sizeΪ 80M ×óÓÒºó£¬ÒÔÉÏÓï¾ä 14s ¼´¿É½â¾ö¡£
Õâ¸ö²ÎÊýÊÇ DBA ºÜÈÝÒ׺öÊӵġ£
Æäʵ£¬²»µ¥µ¥ÊÇÊý¾Ý¿â£¬¾ÍÊDzÙ×÷ϵͳ£¬Ò²ÊÇÊÜ tmp µÄÓ°Ïì¾Þ´ó£¬ÀýÈç°²×°Èí¼þµ½ d: ÅÌ£¬Èç¹û TMP »·¾³±äÁ¿Ö¸Ïò c: ÅÌ£¬¶ø c: ¿Õ¼ä²»¹»£¬ÕÕÑù¿ÉÄܵ¼Ö°²×°Ê§°Ü¡£
Òò´ËÈà TMP ÓÐ×ã¹»µÄ¿Õ¼ä¿ÉÒÔ˵ÊǼÆËã»úϵͳÀïÒ»¸öÆÕ±éÊÊÓõÄÔÔò(д³ÌÐòÒ²ÊÇÒ»Ñù)¡£