我只是在进程列表中找到了“复制到tmp表”这么多查询状态,这些查询运行时间超过40秒。
服务器详细信息:
Server: Localhost via UNIX socket
Server version: 5.5.40-0ubuntu0.12.04.1-log
my.cnf values:
key_buffer_size = 134217728
query_cache_limit = 2097152;
max_heap_table_size = 536870912;
tmp_table_size = 536870912;
concurrent_insert AUTO
low_priority_updates OFF
table_open_cache = 12288;
long_query_time = 2;
max_connections = 300
join_buffer_size=1048576
interactive_timeout=300
wait_timeout=300
innodb_buffer_pool_size =2G;
log-queries-not-using-indexes = OFF
“SHOW STATUS LIKE'qc%'”的结果:
Qcache_free_blocks 12334
Qcache_free_memory 42059504
Qcache_hits 330467210
Qcache_inserts 946786273
Qcache_lowmem_prunes 2815011
Qcache_not_cached 177691822
Qcache_queries_in_cache 21886
Qcache_total_blocks 56201
请建议更好的价值观。
如果需要,请告诉我
(来自评论)
SELECT myid,inb_id,message,date,STATUS
FROM messages
WHERE youid =userid
AND STATUS =3
GROUP BY myid
ORDER BY date DESC
LIMIT 0 , 15
CREATE TABLE messages (
myid int(10) NOT NULL,
youid int(10) NOT NULL,
message text NOT NULL,
date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
inb_id int(11) NOT NULL AUTO_INCREMENT,
readed varchar(30) NOT NULL,
status int(10) NOT NULL,
delete int(11) NOT NULL,
today varchar(20) NOT NULL,
dupdate varchar(20) NOT NULL,
PRIMARY KEY (inb_id),
KEY Idxdate (date),
KEY Idxyouid (youid),
KEY Idxdupdate (dupdate),
KEY Idxid (myid),
KEY Idxmyid (myid,youid),
KEY Idxyouread (youid,readed),
KEY Idxyouid_status (youid,status),
KEY Idxyoudt (youid,status,date)
) ENGINE=InnoDB AUTO_INCREMENT=165893279 DEFAULT CHARSET=latin1
答案 0 :(得分:1)
不要浪费时间使用Copying to tmp table
来诊断慢速查询。这些tmp tables
不是真正的表格。它们是内存结构(如果需要可以溢出到磁盘)。很多查询,尤其是聚合(GROUP BY
和DISTINCT
)查询必须执行此操作才能获得结果。
如果您的查询速度很慢,请逐一查看。对它们使用EXPLAIN
。弄清楚你是否需要新的索引。
http://use-the-index-luke.com/是一个很好的参考。
答案 1 :(得分:0)
如果没有Uptime
,RAM大小query_cache_size
,则输出无效。
table_open_cache
非常高;我希望你没有数千张桌子?tmp_table_size = 536870912
危险地高!它不应超过RAM的1%左右。它为每个查询中的每个tmp表分配。因此,一个巨大的价值可能会导致内存爆炸,从而导致交换,这对性能来说非常糟糕。为了进一步诊断您的问题,请提供
EXPLAIN SELECT ...
,SHOW CREATE TABLE
不,你可能无法“调整你的方式摆脱性能问题”。
更多强>
table_open_cache
降低至200 query_cache_size
降低至50M 更多
KEY Idxyouid (youid),
KEY Idxyouid_status (youid,status),
KEY Idxyoudt (youid,status,date)
在这样的模式中,保留最长的一个,DROP
其他模式。
以下是可能发生的事情:
INDEX(youid, status)
用于查找大约2778行。SELECT
正在提取TEXT
列;文本列,至少如果它们很大,则存储在“非记录”状态。这意味着需要额外的磁盘I / O才能获得该值。我很困惑......
可以youid
向messages
发送多个myid
吗?在您ORDER BY date
的同时,无法 GROUP BY myid
;你会得到一个随机的约会!由于我不理解你的查询,我只能随意提出你的方向......
组合youid, myid, date
不是唯一的,对吗?
那么,解决方案是什么?
message
吗? (省略该列可能消除大部分I / O.)message
,请稍后再抓取。 (更多内容见下文。)youid
获取多行,那么此技术可能非常有效:替换
PRIMARY KEY(inb_id),
INDEX(youid)
与
PRIMARY KEY(youid, date, inb_id) -- to better cluster the rows
INDEX(inb_id) -- to keep AUTO_INCREMENT happy
如果myid
是获取行的常用方法,请使用myid
代替youid
启动PK。
(没有新PK不完美,但它提供了一些好处。)
稍后抓取message
假设我已经正确地确定提取message
是昂贵的部分,并注意到您只需要15条消息,那么让我们重新设计查询以仅提取15个,而不是全部2778个。
我无法弄清楚如何使GROUP BY myid
有意义,所以我删除了它。
SELECT m2.myid, m2.inb_id, m2.message, m2.date, m2.STATUS
FROM
( SELECT inb_id
FROM messages
WHERE youid = 1234
AND STATUS = 3
ORDER BY date DESC
LIMIT 0, 15
) AS m1
JOIN messages AS m2 USING(inb_id)
这个公式中的“秘密酱”是它在“派生表”(即子查询)中发现15个inb_ids,然后只查找那些查找message
的缓慢过程的15个。总时间应约为0.2秒。您现有的KEY Idxyoudt (youid,status,date)
最适合它。