Table:
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
Slow Query Log:
# 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;
...
Explain:
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)
Config:
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
With your covering index already in place, it simply may not be possible. Here is why:
Run these queries:
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;
These queries will show you which paircounts exceed 5% of the total rowcount of the deal_keyword table. Any paircounts exceeding 5% of the rowcount will dismiss the use of the index in the MySQL Query Optimizer and revert to a full table scan.
Keep in mind that since the table is MyISAM, any DML (INSERT, UPDATE or DELETE) will perform a full table lock. This will cause any SELECT count on the deal_keyword table following DML to wait. Also, any burst of multiple SELECTs that come before any DML will make the DML wait.
ALTER TABLE deal_keyword ENGINE=InnoDB;
Counts against an InnoDB would happen as a transaction and would not block other DB Connections performing counts.
I doubt it could be optimized. One ugly way - you could probably store the current count in a separate table with cols: area_id | keyword_id | count
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.