SELECT COUNT(*)超级慢,讨论一下解决方案

2018-05-14 13:35:02 +08:00
 Aluhao

使用场景: 1、回复表 1 亿多数据,每天增长 1 万+; 2、发回复的时候得统计回复用户回复数量;

使用的语句:SELECT COUNT(*) FROM answer WHERE uid='10' 查询结果:6963911 使用时间:101.618 秒 其中 uid 已经索引,也用过其它 COUNT(其它列字段) 查询一样很慢; 如果用 aid 已经索引,aid='10' 查出结果数量少,查询很快;

还能通过优化 SQL 语句来优化吗,如果不行,只能通过 insert +1 及 delete -1 来解决了。

19496 次点击
所在节点    MySQL
67 条回复
VoidChen
2018-05-14 16:12:29 +08:00
count 个字段,不要 count * 。然后就是搞分区。还不行就上 mpp,我用起来感觉 mpp 比 oracle 要快一丢丢,千万级数据的表,没实测,有时间打算试一下
puritania
2018-05-14 16:13:15 +08:00
这种东西用 redis 做个计数器不就完了吗,动态更新计数器。
VoidChen
2018-05-14 16:15:36 +08:00
没看到下面还有详细的不好意思。。。我觉得这种回复用 count 有点反人类了,给个字段 update +1 -1 吧。。。。
linbiaye
2018-05-14 16:16:21 +08:00
说 count(*)不如 count(1), count 字段的都是瞎说,加了索引还慢就考虑其他方案把。看看有没有可能自己维护计数器,估计跑不了拆分了。
kkeiko
2018-05-14 16:22:06 +08:00
说不要 count(*) 的 估计不知道查询优化器这个东西吧,至于楼主这个问题,拆表吧。
Aluhao
2018-05-14 16:59:07 +08:00
@mchl 这样也是很慢的,试过了,估计是内容太多的问题。
dante3imin
2018-05-14 18:01:50 +08:00
我看好多人说 count (*)和 count (字段)的区别,之前看到一篇[博文]( https://blog.ti-node.com/blog/6343811157316337664)
jelinet
2018-05-14 20:41:13 +08:00
我也维护了一个计数的,但因为计数前业务复杂,写了很多逻辑代码,后来又加了锁,有时候真想 count 了之,但理智告诉我绝对不行,继续维护吧。
lihongming
2018-05-14 20:52:43 +08:00
记得 discuz 的做法是+-1,且定时重算
defclass
2018-05-14 21:01:54 +08:00
uid 是 string 还是 integer ? 遇到过一个类似的坑
elarity
2018-05-14 22:25:32 +08:00
@VoidChen 说反了,对于 innodb 引擎,毫无疑问用 count(*),count ( col )弄不好会更慢
Raymon111111
2018-05-14 22:26:09 +08:00
讨论 count(*) 和 count(1) 根本没找到重点

没有使用场景?

如果仅仅希望有一个数量, 两个方法

简单一点直接 redis

复杂一点, 把索引带上时间, 今天以前的回复数量是固定的, 每天零点的时候用离线任务把今天以前的回复数量全统计一遍扔到一个地方. 然后再实时计算今天的回复数量, 索引踩上 (uid,ctime) uid=#{uid} and ctime >#{betweenTime} and ctime< #{endTime}

另外一个上亿每天增长千万的表应该要分库分表或者归档
kn007
2018-05-14 22:29:36 +08:00
建议读取一次后,存入 noSQL,做 incr 和 decr。
aa6563679
2018-05-14 22:33:51 +08:00
只有当天的数据实时统计,以前的数据专门换个表归档
scnace
2018-05-14 22:36:17 +08:00
鸟书上推荐的是维护字段+- 1 只是这样就要引入锁机制(
yangqi
2018-05-14 22:38:49 +08:00
慢说明索引已经不优化了,先分析优化下索引。
lgh
2018-05-14 23:23:24 +08:00
@defclass +1,这个 uid 字段的类型到底是数字还是字符串真的要搞清楚先
rahuahua
2018-05-14 23:43:06 +08:00
uid=10 的数量已经近 700W,(如果数据库服务器内存不是足够大 + 要检索的索引文件不在内存里)索引本身的检索就会造成大量的 I/O,从数据库层面已经无法再优化了。只能从应用层优化了
is99zsq
2018-05-14 23:54:18 +08:00
添加一个表,记录累计值

然后每日做个批量,

查询变成 历史上的累计值+本日实时统计值
vus520
2018-05-14 23:56:40 +08:00
我的老哥,ES 了解一下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/454696

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX