先给出数据表table结构:
字段名 | 含义 |
---|---|
id | 自增ID |
name | 姓名 |
rule_id | 某种规则对应ID |
status | 状态 |
目前数据库中数据大概有2000W条,之后可能还会不断增长,现在想要查询的是:
从表中找出相同姓名,相同规则ID,并且
status = 1
对应的最后一条记录
目前使用的语句,:
SELECT * FROM table WHERE id IN (
SELECT max(id) AS max_id FROM table GROUP BY name, rule_id)
AND status = 1
已经做的优化:添加了name,rule_id的索引
现在查询时,基本直接卡死,根本查询不出来,像这种情况需要如何优化?
包括但不仅包括:
1、SQL语句的优化
2、如何合理的添加索引
各位大神有什么好的优化建议吗?谢谢各位了!!
status
字段应该写在子查询中,这样会高效一点,但具体有多少提升要看status=1
的记录占大多数还是少数。
select * from table where id in (select max(id) as max_id from table where status = 1 GROUP BY name, rule_id)
你先试试,我再想想有没有办法进一步优化
你这个查询语句里面慢应该 实在 id in (...)这个条件上面慢的,mysql在group by的效率其实很高的。
但是group by默认会匹配第一个记录,也就是说如果只执行
select * from table where status = 1 group by name rule_id;
得到的刚好是对应集合里面id最小的那一条记录。
你试试先排序再group一下的效率(把筛选条件放子查询里面,减少group by的数量)
select * from (
select * from table where status = 1 order by id desc
) as t group by name rule_id;
没有测试效率, 但是结果应该是对的。
这里id是索引,排序应该是很快的。
你的sql慢的原因是用了子查询,而你的数据超过2000w,在实际使用中,是绝对强烈不推荐大数据中使用子查询的,你这这句sql可以把数据库服务器拖死。我们的业务中就曾经出现过一句sql拖死整个数据库服务器的案例。谨记。
如果你想用一句sql查出来的话,估计会很慢。
我能想到的办法是分表;或者将你想要的id存在另外的表中。