繁体   English   中英

您如何优化此MySQL慢查询?

[英]How do you optimize this MySQL slow query?

表:

CREATE TABLE `deal_keyword` (
  `deal_id` int(11) NOT NULL default '0',
  `keyword_id` int(11) NOT NULL default '0',
  `area_id` int(11) NOT NULL default '0',
  PRIMARY KEY  (`deal_id`,`keyword_id`),
  KEY `area_id` (`area_id`,`keyword_id`,`deal_id`)
) TYPE=MyISAM

慢查询日志:

# Time: 111115  0:18:11
# Query_time: 2  Lock_time: 0  Rows_sent: 1  Rows_examined: 3629
select count(deal_id) from deal_keyword where area_id=101 && keyword_id=115;

# Time: 111115  0:34:55
# Query_time: 2  Lock_time: 0  Rows_sent: 1  Rows_examined: 5778
select count(deal_id) from deal_keyword where area_id=101 && keyword_id=142;

# Time: 111115  0:36:05
# Query_time: 3  Lock_time: 0  Rows_sent: 1  Rows_examined: 4433
select count(deal_id) from deal_keyword where area_id=101 && keyword_id=112;

# Time: 111115  0:36:06
# Query_time: 2  Lock_time: 0  Rows_sent: 1  Rows_examined: 1955
select count(deal_id) from deal_keyword where area_id=101 && keyword_id=533;

...

说明:

mysql> explain select count(deal_id) from deal_keyword where area_id=101 && keyword_id=115;
+--------------+------+---------------+---------+---------+-------------+------+--------------------------+
| table        | type | possible_keys | key     | key_len | ref         | rows | Extra                    |
+--------------+------+---------------+---------+---------+-------------+------+--------------------------+
| deal_keyword | ref  | area_id       | area_id |       8 | const,const | 4632 | Using where; Using index |
+--------------+------+---------------+---------+---------+-------------+------+--------------------------+
1 row in set (0.00 sec)

配置:

key_buffer=512M
max_allowed_packet=8M
table_cache=512
sort_buffer=8M
record_buffer=8M
thread_cache=8
thread_concurrency=4
myisam_sort_buffer_size=128M
interactive_timeout=28800
wait_timeout=7200

在您的覆盖指数已准备就绪的情况下,根本不可能。 原因如下:

运行以下查询:

SELECT COUNT(1) INTO @rowcount from deal_keyword;
SELECT FLOOR(COUNT(1) * 0.05) into @fivepct from deal_keyword;
SELECT @rowcount,@fivepct;
SELECT area_id,keyword_id,COUNT(1) paircount
FROM deal_keyword GROUP BY area_id,keyword_id
HAVING COUNT(1) >= @fivepct;

这些查询将向您显示哪些对数超过Deal_keyword表总行数的5%。 任何超过行数5%的结对计数都将取消MySQL Query Optimizer中索引的使用,并恢复为全表扫描。

请记住,由于表是MyISAM,所以任何DML(INSERT,UPDATE或DELETE)都将执行全表锁定。 这将导致DML之后的Deal_keyword表上的所有SELECT计数都将等待。 同样,在任何DML之前出现的多个SELECT突发都会使DML等待。

建议:将表转换为InnoDB

ALTER TABLE deal_keyword ENGINE=InnoDB;

InnoDB的计数将作为事务发生,并且不会阻止其他执行计数的DB Connections。

我怀疑它是否可以优化。 一种丑陋的方式-您可能会将当前计数存储在带有cols的单独表中: keyword_id | 计数

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM