[英]How to make this complicated query faster [MySQL]?
I have the next query: 我有下一个查询:
SELECT JL.j_id, COUNT(*) as total
FROM j_log JL
WHERE JL.log_time > '20120205164008'
AND JL.j_id IN (
SELECT j_id
FROM j
WHERE checked = '1'
AND expires >= '20120207164008'
) GROUP BY JL.j_id ORDER BY total DESC LIMIT 3
j table has big structure 100 fields and 248986 rows inside it. j表具有100个字段和248986行的大结构。
next KEY's are present in it 里面有下一个钥匙
PRIMARY KEY (`j_id`),
KEY `expires` (`expires`),
KEY `checked` (`checked`),
KEY `checked_2` (`checked`,`expires`)
j_log table has about 63000000 records and the next structure j_log表具有大约63000000条记录和下一个结构
CREATE TABLE `j_log` (
`j_id` int(11) NOT NULL DEFAULT '0',
`member_id` int(11) DEFAULT NULL,
`ip` int(10) unsigned NOT NULL DEFAULT '0',
`log_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY `j_id` (`j_id`),
KEY `log_time` (`log_time`),
KEY `ip` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
so the considered query wants to get top3 of most visited j_id instances 因此考虑的查询希望获得访问量最大的j_id实例的top3
this is the plan 这是计划
+----+--------------------+-------+-----------------+-----------------------------------+---------+---------+------+----------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+-------+-----------------+-----------------------------------+---------+---------+------+----------+----------+----------------------------------------------+
| 1 | PRIMARY | JL | index | log_time | j_id | 4 | NULL | 63914602 | 0.36 | Using where; Using temporary; Using filesort |
| 2 | DEPENDENT SUBQUERY | j | unique_subquery | PRIMARY,expires,checked,checked_2 | PRIMARY | 4 | func | 1 | 100.00 | Using where |
+----+--------------------+-------+-----------------+-----------------------------------+---------+---------+------+----------+----------+----------------------------------------------+
Some times it could take up for 15!!! 有时可能会占用15个!!! minutes.
分钟。
Is there any way how to make faster ? 有什么办法可以使速度更快?
SELECT JL.j_id, COUNT(*) as total
FROM j_log JL
INNER JOIN j
ON JL.j_id = j.j_id
AND j.checked = '1'
AND j.expires >= '20120207164008'
WHERE JL.log_time > '20120205164008'
GROUP BY JL.j_id
ORDER BY total
DESC LIMIT 3
Will this be faster? 这样会更快吗?
checked
a string? checked
字符串? ('1' instead of just 1) jl.log_time
and j.expires
diffrently ( >
vs >=
) jl.log_time
和j.expires
( >
vs >=
) How about this query 这个查询怎么样
SELECT j.j_id, COUNT(jl.j_id) as total
FROM j
LEFT JOIN j_log jl ON (jl.j_id = j.j_id AND jl.checked = '1' AND jl.log_time > '20120205164008')
WHERE j.expires >= '20120207164008'
GROUP BY j.j_id
ORDER BY total DESC
LIMIT 3
Make sure j_id
is the PRIMARY KEY
for both tables and put an index on j.expires and jl.checked and jl.logtime. 确保
j_id
是两个表的PRIMARY KEY
,并在j.expires和jl.checked和jl.logtime上放置索引。 Also make sure the field checked
is optimized. 还要确保
checked
的字段已优化。 I'm not sure what the possible values can be, but I assume it's a boolean field. 我不确定可能的值是多少,但是我认为这是一个布尔字段。 So rather make the field_type
BIT
or use an ENUM
因此,宁可将field_type设为
BIT
或使用ENUM
Edit 编辑
Also you should convert the fields j.expires
and jl.log_time
to better fields. 另外,您应该将字段
j.expires
和jl.log_time
转换为更好的字段。 I think it is just a varchar
now, looking at the current value you use: 20120205164008. Convert this into a DATETIME
field (but don't just convert the tables because you will lose the data). 我认为现在只是一个
varchar
,查看您使用的当前值:20120205164008。将其转换为DATETIME
字段(但不要只是转换表,因为这样会丢失数据)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.