我正在运行一个广泛查询MySQL数据库的站点。查询数据库服务器的某些页面加载速度非常慢,我很确定这是由于数据库服务器造成的。通过查看数据库服务器的使用情况,我可以看到iowait> 10秒,交换空间也被部分使用。打开慢查询日志后,我发现一个查询一直很慢。查询看起来像
select g.citing from g, c where g.cited=8992 and g.citing=c.id order by c.size desc limit 20;
典型查询时间约为10秒。 innodb_buffer_pool_size设置为24GB。我读了一些MySQL手册页,发现我可能需要调整sort_buffer_size参数,因为Sort_merge_passes
状态变量非常高(大约310818)。 sort_buffer_size
的当前值是2M,我不确定是否应该上升或下降,因为有些人说永远不会超过2M。
当前查询不利用索引。 " EXPLAIN"的结果声明给出了以下结果:
+----+-------------+-----------+--------+---------------+---------+---------+--------------------------------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+--------+---------------+---------+---------+--------------------------------+------+---------------------------------+
| 1 | SIMPLE | g | ref | citing,cited | cited | 8 | const | 306 | Using temporary; Using filesort |
| 1 | SIMPLE | c | eq_ref | PRIMARY,id | PRIMARY | 8 | db1.g.citing | 1 | |
+----+-------------+-----------+--------+---------------+---------+---------+--------------------------------+------+---------------------------------+
我试图考虑一个更好的查询,它可以利用索引,但现在没有运气。谁能帮我吗?我很感激。
答案 0 :(得分:1)
如果你能避免它,那就不行了。
在增加任何类型的内存分配之前,请尝试寻找替代解决方案。通常这将是两件事中的一件(或两件):查询优化和索引。
在您的情况下,可以非常显着地优化查询。它目前正在做的是查询g
中的每一行乘以 c
中的每一行,然后应用where
子句,然后{{{} 1}},然后是order by
。
如果您使用联接,请执行以下操作:
limit
这样做是为了查询select g.citing from g
inner join c on g.citing=c.id
where g.cited=8992
order by c.size desc
limit 20;
中的每一行,然后查询g
中的每一行以查找匹配项,然后在两个表的交集处应用c
子句 - 行数比以前少得多 - 其次是where
和order by
。
使用c.id上的主索引和g.citing和g.cited上的索引,你应该提高速度并进一步降低内存使用量。
答案 1 :(得分:0)
只有一个状态变量关心sort_buffer_size。 MySQL文档说:
Sort_merge_passes:排序算法必须执行的合并通过次数。如果此值很大,则应考虑增加sort_buffer_size系统变量的值。
请记住关于sort_buffer_size的一件事。
如果在SHOW GLOBAL STATUS输出中看到每秒有很多Sort_merge_passes,则可以考虑增加sort_buffer_size值以加快ORDER BY或GROUP BY操作,这些操作无法通过查询优化或改进的索引来改善
提高sort_buffer_size
可以帮助查询GROUP BY
和ORDER BY
的同时,最好改进可改进的查询并添加索引可以由查询优化器使用。
问题仍然存在:如何检查Sort_merge_passes Sort_merge_passes?
使用此代码,检查最近5分钟内发生了多少次Sort_merge_passes。它还会计算每小时的Sort_merge_passes。
SET @SleepTime = 300;
SELECT variable_value INTO @SMP1
FROM information_schema.global_status WHERE variable_name = 'Sort_merge_passes';
SELECT SLEEP(@SleepTime) INTO @x;
SELECT variable_value INTO @SMP2
FROM information_schema.global_status WHERE variable_name = 'Sort_merge_passes';
SET @SMP = @SMP2 - @SMP1;
SET @SMP_RATE = @SMP * 3600 / @SleepTime;
SELECT @SMP,@SMP_RATE;
如果您发现Sort_merge_passes和速率太高,请随时增加sort_buffer_size。假设您想提高到4M。您将运行以下代码:
mysql> SET GLOBAL sort_buffer_size = 1024 * 1024 * 4;
然后将其添加到my.cnf
[mysqld]
sort_buffer_size = 4M
您将定期运行代码以检查是否有其他时间Sort_merge_passes峰值。