mysql使用更好的值优化查询

mysql使用更好的值优化查询,mysql,optimization,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_

我只是在进程列表中发现了这么多关于“复制到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
“显示状态如“qc%”的结果:

请建议更好的价值观

如果需要什么,请告诉我

(来自评论)


不要浪费时间使用
复制到tmp表
作为诊断慢速查询的方法。这些
tmp表
并不是真正的表。它们是内存结构(如果需要,可以溢出到磁盘)。许多查询,尤其是aggreage(
groupby
DISTINCT
)查询必须这样做才能得到结果

如果查询速度慢,请逐个查看。对它们使用
解释
。弄清楚是否需要新索引


是一个很好的参考。

如果没有
正常运行时间、RAM大小、
查询缓存大小,那么输出就没有用处

  • 表\u打开\u缓存
    非常高;我希望你没有成千上万张桌子
  • tmp\u table\u size=536870912
    高得危险!它不应该超过RAM的1%。它被分配给每个查询中的每个tmp表。所以,一个很大的值可能会耗尽RAM,导致交换,这对性能是不利的
为了进一步诊断您的问题,请提供

  • 选择
  • 解释选择…
  • 显示创建表
不,您可能无法“调整您的方式以解决性能问题”

更多

    KEY Idxyouid        (youid), 
    KEY Idxyouid_status (youid,status), 
    KEY Idxyoudt        (youid,status,date)
  • 表\u打开\u缓存
    降低到200
  • 查询缓存大小
    降低到50米
更多更多

    KEY Idxyouid        (youid), 
    KEY Idxyouid_status (youid,status), 
    KEY Idxyoudt        (youid,status,date)
在这样的模式中,保留最长的一个,
DROP
其他的

下面是可能发生的情况:

  • 索引(youid,status)
    用于查找大约2778行
  • 那些行分散在桌子周围
  • 表太大,无法缓存在RAM中
  • SELECT
    正在获取一个
    TEXT
    列;文本列(至少是较大的文本列)存储为“非记录”。这意味着需要额外的磁盘I/O来获取该值
  • 硬盘上的2778 I/O大约需要27.78秒(粗略的经验法则是100 IOPs)
  • 27.78接近测得的40,我可以宣布我已经推断出了问题
  • (注意,“复制到tmp表”并没有提供有用的线索。)
我很困惑

youid
可以向
myid
发送多条
消息吗?您不能在按myid分组的同时按日期下单
;你会得到一个随机的日期!因为我不明白你的疑问,我只能随便给你一些想法

组合
youid、myid、date
不是唯一的,对吗

那么,解决方案是什么

  • 您需要
    信息吗?(省略该列可能会消除大部分I/O。)
  • 如果您确实需要
    消息
    ,请稍后再获取。(更多信息,请参见下文。)
  • 如果通常根据
    youid
    获取多行,则此技术可能非常有效:
替换

PRIMARY KEY(inb_id),
INDEX(youid)

如果
myid
是获取行的常用方法,则使用
myid
而不是
youid
启动PK

(不,新的PK并不完美,但它提供了一些好处。)

抓取
消息
稍后

假设我已经正确地识别了获取
消息
是代价高昂的部分,并且注意到您只需要15条消息,那么让我们重新格式化查询,只获取15条,而不是全部2778条

我不知道如何使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个inb_ID以查找
消息的缓慢过程。总时间应为0.2秒左右。您现有的<代码>密钥IDXYDT(YouID,Stand,DATE)<代码>是最合适的。

考虑在TMP表上读取一些内容:考虑使用RAMDISE加快速度。HI感谢回复正常运行时间:6232200 RAM大小:4GB表:100查询:选择MyID、IbjID、消息、日期、来自消息的状态,其中youid=userid,STATUS=3按myid分组按日期说明限制0,15解释:id选择类型表类型可能的键键键长度参考行额外1个简单消息参考Idxyouidstatus Idxyouidstatus 8常量,常量2778使用WHERE;使用临时设备;使用filesortquery_cache_size=268435456;(增加了更多);
userid
是常数;它来自哪里?大约在
消息中有多少行?您从查询中返回了大约2778行吗?
PRIMARY KEY(youid, date, inb_id)  -- to better cluster the rows
INDEX(inb_id)  -- to keep AUTO_INCREMENT happy
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)