【问题标题】:Slow MySQL Query not using filesort不使用文件排序的慢 MySQL 查询
【发布时间】:2011-02-15 06:05:30
【问题描述】:

我的主页上有一个查询随着我的数据库表变大而变得越来越慢。

表名 = tweets_cache 行数 = 572,327

这是我当前使用的查询,速度很慢,超过 5 秒。

SELECT * FROM tweets_cache t WHERE t.province='' AND t.mp='0' ORDER BY t.published DESC LIMIT 50;

如果我取出 WHERE 或 ORDER BY,则查询超快 0.016 秒。

我在 tweets_cache 表上有以下索引。

PRIMARY
published
mp
category
province
author

所以我不确定为什么它不使用索引,因为 mp、provice 和 published 都有索引?对查询进行分析表明它没有使用索引对查询进行排序,而是使用了文件排序,这真的很慢。

possible_keys = mp,province
Extra = Using where; Using filesort

我尝试使用“profiles & mp”添加一个新的多列索引。解释显示,这个新索引列在“possible_keys”和“key”下,但查询时间不变,仍然超过5秒。

这是查询中的分析器信息的screenshot

有些奇怪,我转储了我的数据库以在本地桌面上进行测试,这样我就不会搞砸实时站点。我本地的相同查询运行速度超快,毫秒。因此,我将所有相同的 mysql 启动变量从服务器复制到本地,以确保没有某些设置可能导致这种情况。但即使在此之后本地查询运行速度非常快,但实时服务器上的查询超过 5 秒。

我的数据库服务器只使用了它可用的 4GB 中的大约 800MB。 这是我正在使用的相关 my.ini 设置

默认存储引擎 = MISAM
最大连接数 = 800
跳过锁定
key_buffer = 512M
max_allowed_pa​​cket = 1M
表缓存 = 512
sort_buffer_size = 4M
读取缓冲区大小 = 4M
read_rnd_buffer_size = 16M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size = 128M
# 尝试线程并发的 CPU 数量*2
thread_concurrency = 8
# 默认禁用联合
跳过联合

key_buffer = 512M
排序缓冲区大小 = 256M
read_buffer = 2M
write_buffer = 2M

key_buffer = 512M
排序缓冲区大小 = 256M
read_buffer = 2M
write_buffer = 2M

MySQL 5.0.67

CREATE TABLE `tweets_cache` (                                                             
            `id` bigint(11) unsigned NOT NULL default '0',                                          
            `published` int(11) NOT NULL default '0',                                               
            `title` varchar(140) NOT NULL,                                                          
            `category` varchar(50) NOT NULL,                                                        
            `type` varchar(30) NOT NULL,                                                            
            `author` varchar(25) NOT NULL,                                                          
            `author_full` varchar(150) NOT NULL,                                                    
            `hash` varchar(50) NOT NULL,                                                            
            `lastupdate` int(11) NOT NULL default '0',                                              
            `avatar` varchar(120) NOT NULL,                                                         
            `mp` int(1) NOT NULL default '0',                                                       
            `followers` int(10) NOT NULL default '0',                                               
            `province` varchar(2) NOT NULL,                                                         
            `talkback` varchar(15) NOT NULL default '',                                             
            `in_reply_to_status_id` bigint(11) unsigned NOT NULL default '0',                       
            `author_id` int(11) NOT NULL default '0',                                               
            `tracked` tinyint(1) NOT NULL default '0',                                              
            `geo` varchar(25) NOT NULL default '',                                                  
            PRIMARY KEY  (`id`),                                                                    
            KEY `published` (`published`),                                                          
            KEY `mp` (`mp`),                                                                        
            KEY `category` (`category`),                                                            
            KEY `province` (`province`),                                                            
            KEY `author` USING BTREE (`author`),                                                    
            KEY `home` (`province`,`mp`,`published`)                                                
          ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='InnoDB free: 275456 kB'

【问题讨论】:

  • 您使用的是什么版本的 MySql。还请在此处删除“显示创建表”定义...

标签: mysql performance


【解决方案1】:

我不确定为什么它不使用索引,因为 mp、provice 和 published 都有索引?

MySQL 只会在整个表中使用一个索引。如果您想在同一步骤中执行 WHERE 和 ORDER BY,请创建一个复合索引,其中包含左侧的匹配条件和右侧的排序条件,例如。在这种情况下(province, mp, published)

关于ORDER BY optimisation

【讨论】:

  • 天哪,谢谢,我在多列索引中添加了“已发布”,现在查询需要 0.015 秒!所以我为像“mp,provice”这样的单列所拥有的所有索引都是无用的,因为我的查询中总是有一个 ORDER BY?
  • 它们并非完全无用;如果mp 不存在,仅基于mp 的查询会更慢!但是,是的,拥有大量单列索引往往没有您想象的那么大帮助。
  • 所以将我所有的索引都转换为多列索引会更好,因为我总是按发布排序。例如将“mp”转换为“mp,published”
  • 是的。复合索引还用于索引左子集,即。如果您在 (province, mp) 上创建了索引,您可以在 WHERE province= 上创建查询,但不能在 WHERE mp= 上创建索引。
【解决方案2】:

尝试将查询分成两部分,这样两个索引都可以工作,例如:

CREATE TEMPORARY TABLE cache
SELECT -describefields- FROM tweets_cache t WHERE t.province='' AND t.mp='0';

SELECT * FROM cache c ORDER BY c.published DESC LIMIT 50;

【讨论】:

  • 临时表在 MySQL 中不能有(和使用)索引。
猜你喜欢
  • 1970-01-01
  • 2013-09-15
  • 2023-04-09
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
  • 2011-03-02
  • 2012-04-17
  • 2012-08-22
相关资源
最近更新 更多