mysql使用更好的值优化查询

时间:2017-09-14 10:21:53

标签: mysql optimization

我只是在进程列表中找到了“复制到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

2 个答案:

答案 0 :(得分:1)

不要浪费时间使用Copying to tmp table来诊断慢速查询。这些tmp tables不是真正的表格。它们是内存结构(如果需要可以溢出到磁盘)。很多查询,尤其是聚合(GROUP BYDISTINCT)查询必须执行此操作才能获得结果。

如果您的查询速度很慢,请逐一查看。对它们使用EXPLAIN。弄清楚你是否需要新的索引。

http://use-the-index-luke.com/是一个很好的参考。

答案 1 :(得分:0)

如果没有Uptime,RAM大小query_cache_size,则输出无效。

  • table_open_cache非常高;我希望你没有数千张桌子?
  • tmp_table_size = 536870912危险地高!它不应超过RAM的1%左右。它为每个查询中的每个tmp表分配。因此,一个巨大的价值可能会导致内存爆炸,从而导致交换,这对性能来说非常糟糕。

为了进一步诊断您的问题,请提供

  • SELECT,
  • 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行。
  • 这些行分散在桌子周围。
  • 该表太大而无法缓存在RAM中。
  • SELECT正在提取TEXT列;文本列,至少如果它们很大,则存储在“非记录”状态。这意味着需要额外的磁盘I / O才能获得该值。
  • 2778 HDD上的I / O大约需要27.78秒(粗略的经验法则是100 IOP)。
  • 27.78足以接近我所测量的40,声明我已经推断出这个问题了。
  • (请注意,“复制到tmp表”没有提供有用的线索。)

我很困惑......

可以youidmessages发送多个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)最适合它。