【问题标题】:mysql optimizing queries with better valuesmysql用更好的值优化查询
【发布时间】:2017-09-15 23:44:02
【问题描述】:

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

请提出更好的值。

如果有什么需要请告诉我

(来自 cmets)

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

【问题讨论】:

标签: mysql optimization


【解决方案1】:

不要浪费时间使用Copying to tmp table 作为诊断慢查询的方法。这些tmp tables 并不是真正的表格。它们是内存结构(如果需要,可以溢出到磁盘)。大量查询,尤其是聚合(GROUP BYDISTINCT)查询必须这样做才能获得结果。

如果您的查询速度较慢,请一一查看。在他们身上使用EXPLAIN。弄清楚你是否需要新的索引。

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

【讨论】:

    【解决方案2】:

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

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

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

    • 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 才能获得价值。
    • HDD 上的 2778 次 I/O 大约需要 27.78 秒(粗略的经验法则是 100 次 IOP)。
    • 27.78 足够接近实测值 40,我可以声明我已经推断出问题。
    • (请注意,“复制到 tmp 表”没有提供有用的线索。)

    我很困惑……

    youid 可以向myid 发送多个messages 吗?你不能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_id,然后仅查找这 15 个以查找message 的缓慢过程。总时间应约为 0.2 秒。而您现有的 KEY Idxyoudt (youid,status,date) 最适合它。

    【讨论】:

    • 您好,感谢您的回复 Uptime: 6232200 Ram Size: 4GB Tables: 100
    • 查询: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 说明:id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE messages ref Idxyouidstatus Idxyouidstatus 8 const,const 2778 使用 where;使用临时的;使用文件排序
    • query_cache_size = 268435456;
    • (添加更多); userid 是常量吗?它来自哪里?
    • messages 大约有多少行?您是否从查询中返回了大约 2778 行?
    猜你喜欢
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-18
    • 1970-01-01
    • 2011-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多