mysql使用更好的值优化查询
我只是在进程列表中发现了这么多关于“复制到tmp表”状态的查询,这些查询的运行时间超过了40秒 服务器详细信息: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_
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)