数据库查询优化问题,有没有老哥懂的?

2023-02-01 17:05:41 +08:00
 cy1027

SELECT id FROM table_name;--一秒钟出结果,我的表大概三十万数据 select count(id) from table_name;--超过二十秒,没等它跑完 select count() from table_name;--同上 id 是主键,数据库里有很多列,有大量字符串,大概占几个 g 的磁盘。 我比较不理解,为什么只查 id 可以很快,但是对 id 计数就会很慢,如果说 count ()要扫描全表,那 count ( id )不应该只比第一个稍微慢一丢丢么?

2242 次点击
所在节点    程序员
41 条回复
aw2350
2023-02-01 17:09:25 +08:00
count(*) 忽略 null
count(id) 筛查 id<> null
cstj0505
2023-02-01 17:11:32 +08:00
SELECT id FROM table_name 只是查出了一部分,可能就几十条,不是全部查出,你的数据库工具也没有把 30 万 id 都放内存里吧。
select count(id) from table_name 需要全部查出
adoal
2023-02-01 17:12:43 +08:00
如 #2 所说。

你的 SELECT id 是在哪里运行的,怎样算是“出结果”?
opengps
2023-02-01 17:20:11 +08:00
id 列自身就是个索引。
回归下实体案例理解下:你那本新华字典,真正内容厚 5cm (全文扫描),但你只看索引(执行 count(id) )只需要 0.5cm
cy1027
2023-02-01 17:23:38 +08:00
@adoal
@cstj0505 其实用什么工具查没影响的,我用的是 navicat ,在查询标签里面手打的 sql 语句,连远程数据库查的,直接查 id 本地查到了 40 万(刚刚数据库又增加了一些数据)数据,每个 id 都有,但是无序,我是拖动滚动条看的,右下角会显示“第 1 条”到“第 400000 条”的字样,由于数据库还在更新,现在查 id 大概在 3s 以内,查 count 还是远超 20 秒
leahoop
2023-02-01 17:29:19 +08:00
navicat 默认给你查 1000 条所以很快,你试试 limit 400000 全查出来应该也慢。id 是主键应该不可 null,直接用 count(*)和 count(1)性能是最快的
jixiangqd
2023-02-01 18:10:58 +08:00
什么数据库?什么版本?什么存储引擎?
这些都没说怎么分析数据库里怎么跑的?
encro
2023-02-01 18:13:11 +08:00
没有优化方法途径。count 就是慢。order by 也是慢
qua
2023-02-01 18:27:59 +08:00
可能是 SELECT id FROM table_name 被 navicat 自动加了 limit
LostPrayers
2023-02-01 18:30:01 +08:00
innodb 的大表 count 就是难搞。
1. 如果只有一个 id 索引,然后表又很大, 解决方案是加一个非主键索引,然后查询用 count(*), 它会挑最小数据量的索引进行统计。
2. 使用其他取巧方法:
比如 id 是自增的,从 0 开始,那么最大的 id 就是总数。
比如用 show table status, 虽然不准但勉强够用.
比如上缓存, 程序启动时候查一次缓存起来, 业务更新缓存.
3. 改需求,不要 count 全表。比如后台的管理列表的分页, 就可以只查询前 10W 条,其他情况下带精确的查询条件时再解除限制。
seers
2023-02-01 18:32:06 +08:00
覆盖索引
v2eb
2023-02-01 18:32:42 +08:00
看看表结构
encro
2023-02-01 18:33:15 +08:00
navicat 的统计自动走了统计表,不是准确的。

count 是必须准确的,而且是需要考虑脏数据。
fengpan567
2023-02-01 18:34:19 +08:00
explain select count(id) from table_name; 看看用的什么索引,索引长度是多少
encro
2023-02-01 18:41:55 +08:00
关系数据库几个很多无法解决的问题:

1,count 慢
2,order by xxx limit 1000000,10 (取最后页的慢)
3,like “%xxx”慢
4,没有合理建立索引慢
5,自动更新物理试图
6,。。。

以上等等限制才会有 es,mongo,hbase,redis,InfluxDB,GDB 等等的机会。以上导致关系数据库没有走主键索引的话也就千万级别数据量比较合适吧。如果都是走主键那随便放。
PythonYXY
2023-02-01 18:52:38 +08:00
你把两个 sql 的执行过程贴出来
luozic
2023-02-01 18:53:23 +08:00
看执行计划,时间花在哪了。。。
hhjswf
2023-02-01 18:58:40 +08:00
我寻思 count 可不就必须全盘扫描了,还搁着索引呢。。有用吗
hhjswf
2023-02-01 19:10:02 +08:00
应该是 count 用了临时表
shore123
2023-02-01 19:10:48 +08:00
因为你 SELECT id FROM table_name; 这条查询的是第一页吧....

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

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

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

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

© 2021 V2EX