MySQL 查询数据太慢了,该怎么优化?

2021-12-27 12:02:10 +08:00
 182247236

sql 执行语句 SELECT timestrap, bps FROM cdn_bandwidth WHERE (company_id = 1 AND domain_id IN (242,292,194,264,217,195,203,200,198,221,227,335,167,243,261,218,196,176,174,162,161,160,170,173,325,169,324,171,236,241,220,256,276,186,263,254,286,287,285,288,283,278,291,215,334,260,321,316,318,319,323,322,163,159,213,207,238,274,164,333,280,249,247,246,252,273,255,181,180,248,226,178,179,293,265,301,237,175,240,262,166,305,326,304,165,177,259,225,183,214,193,197,206,290,257,258,219,189,172,209,267,210,271,272,229,302,300,303,275,320,239,284,205,208,182,191,190,277,250,298,295,297,269,216,187,232,230,231,251,185,294,244,245,281,168,268,188,184,223,202,222,192,224,332,282,199,270,266,289,296,234,253,201,233,235,279,211,315,228,204,212) AND time BETWEEN '2021-12-01 00:00:00' AND '2021-12-26 23:59:59')

查询出 1038259 条数据,共花费时间 125 秒。太长时间了。有没有办法能优化下。

7948 次点击
所在节点    MySQL
84 条回复
SmiteChow
2021-12-27 17:54:05 +08:00
explain
PeterZeng
2021-12-27 17:56:46 +08:00
你查询结果字段在没在联合索引里面,不在还要回表查那就很慢了
fiypig
2021-12-27 18:01:33 +08:00
定时器报表统计啊
chuann
2021-12-27 18:07:40 +08:00
SELECT [...] FROM cdn_bandwidth WHERE [...] force index [explain 结果中那个 possible_keys]
icaca
2021-12-28 07:47:52 +08:00
我之前看错了 以为表有 100w 数据
实际情况是查询结果有 100w 那基本上快不起来的(查询和传输)另外这么多数据应用端也容易挂掉 最好还是优化业务 降低返回的结果集的数量
建议是
尽量在数据库完成统计(我看业务并不复杂,应该 group by + sum ,就能搞定了吧?)
实在不行就做一个统计的服务,最终效果肯定好很多,但是维护起来会麻烦一些(主要是害怕统计业务挂掉)
void1900
2021-12-28 09:21:00 +08:00
每个域名单独查
opengps
2021-12-28 09:37:09 +08:00
粗略的办法:where 用到哪些列,就给那些列来个组合索引
yogapants
2021-12-28 09:37:41 +08:00
估计是数据太大,服务器硬件怎么样,数据库服务器是否是专机专用的有跑其他服务么,explain 一下看看啥原因,查询字段加索引尽量走覆盖索引,如果真的是数据量太大不行就上 TIDB 试一下。实在不行专门起一个定时服务项目跑统计服务,放到 redis 里面。
vone
2021-12-28 10:14:16 +08:00
> 因为查询最后需要合并数据结果,就查询的所有域名的相同时间的数据相加,这部因为觉得查询就很慢了,所以返回结果用 python 计算了

这句话应该是错的,sum 并不耗时,把 100w 行数据取回本地才是非常耗时的操作。
nekoneko
2021-12-28 10:54:04 +08:00
1. 明显的没走索引
2. 先 count(*) 或者 sum 看看去掉数据传输用时多久,应该也不会快
3. 联合索引去掉 domain_id,先 time 后 company_id 试试,考虑到回表把 timestrap 和 bps 也加到索引里面
tyrantZhao
2021-12-28 11:13:08 +08:00
返回 100w 数据感觉也正常吧,数据量太大了
vinceall
2021-12-28 11:13:46 +08:00
company_id domain_id time 加索引,explain 看看,会不会锁表
vinceall
2021-12-28 11:17:16 +08:00
@182247236 就是强制索引
nekoneko
2021-12-28 11:24:32 +08:00
@nekoneko #70 domain_id 好像还不能从索引中去掉,考虑下调换顺序,并且用 btree 类型的索引
Protocol
2021-12-28 12:09:16 +08:00
解决了吗,楼主更新下问题进度
MartinWu
2021-12-28 14:42:33 +08:00
建议直接上 clickhouse ,加个 mysql engine 表,然后创建一个物化视图。
liuhouer
2021-12-28 14:54:39 +08:00
clickhouse + cloudcanal ,表用 replacemergetree ,设置自动 optimize ,0.1 秒返回结果,压缩率是 mysql 的 7+倍
changs1986
2021-12-29 11:59:25 +08:00
看 explain, 走的 domain_id 索引, domain_id 区分度可能不太好. 建议调整下 time 的索引, 调整成 index(time, domain_id, company_id), 然后 where 改成 where time BETWEEN '2021-12-01 00:00:00' AND '2021-12-26 23:59:59' and domain_id in (xx,xx) and company_id=1
182247236
2021-12-30 16:36:25 +08:00
因为数据库是在不熟悉,公司只有一位稍微懂点的同事,给我的意见都是分表,因为 IN 的条件太多了,无论如何都快不了的,所以还是用了最笨的方法,按天查询,每次返回的结果在用 pandas 处理,一个月的数据其实就是请求数据库 30 次,速度已经从 120s 降到了 20s ,虽然还是觉得太慢了,接下来试试能不能从多线程的思路解决,提高请求 mysql 的效率看看能不能再优化下,谢谢各位大佬。
ouxch
2021-12-31 13:27:36 +08:00
初看这个问题,从已提供的信息来看,只修改 sql 应该就能得到很大的优化,对索引调整可进一步优化。
如不介意提供下:表结构语句、行数、期望输出、数据库实例(所在机器)的 CPU 核心数和内存大小

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

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

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

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

© 2021 V2EX