1

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

 1 year ago
source link: https://www.v2ex.com/t/912315
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

V2EX  ›  程序员

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

  cy1027 · 7 小时 7 分钟前 · 989 次点击

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

23 条回复    2023-02-01 21:21:01 +08:00
aw2350

aw2350      7 小时 4 分钟前

count(*) 忽略 null
count(id) 筛查 id<> null
cstj0505

cstj0505      7 小时 2 分钟前

SELECT id FROM table_name 只是查出了一部分,可能就几十条,不是全部查出,你的数据库工具也没有把 30 万 id 都放内存里吧。
select count(id) from table_name 需要全部查出
adoal

adoal      7 小时 0 分钟前

如 #2 所说。

你的 SELECT id 是在哪里运行的,怎样算是“出结果”?
opengps

opengps      6 小时 53 分钟前

id 列自身就是个索引。
回归下实体案例理解下:你那本新华字典,真正内容厚 5cm (全文扫描),但你只看索引(执行 count(id) )只需要 0.5cm
cy1027

cy1027      6 小时 49 分钟前

@adoal
@cstj0505 其实用什么工具查没影响的,我用的是 navicat ,在查询标签里面手打的 sql 语句,连远程数据库查的,直接查 id 本地查到了 40 万(刚刚数据库又增加了一些数据)数据,每个 id 都有,但是无序,我是拖动滚动条看的,右下角会显示“第 1 条”到“第 400000 条”的字样,由于数据库还在更新,现在查 id 大概在 3s 以内,查 count 还是远超 20 秒
leahoop

leahoop      6 小时 44 分钟前

navicat 默认给你查 1000 条所以很快,你试试 limit 400000 全查出来应该也慢。id 是主键应该不可 null,直接用 count(*)和 count(1)性能是最快的
jixiangqd

jixiangqd      6 小时 2 分钟前   ❤️ 1

什么数据库?什么版本?什么存储引擎?
这些都没说怎么分析数据库里怎么跑的?
encro

encro      6 小时 0 分钟前

没有优化方法途径。count 就是慢。order by 也是慢
qua

qua      5 小时 45 分钟前 via Android

可能是 SELECT id FROM table_name 被 navicat 自动加了 limit
LostPrayers

LostPrayers      5 小时 43 分钟前

innodb 的大表 count 就是难搞。
1. 如果只有一个 id 索引,然后表又很大, 解决方案是加一个非主键索引,然后查询用 count(*), 它会挑最小数据量的索引进行统计。
2. 使用其他取巧方法:
比如 id 是自增的,从 0 开始,那么最大的 id 就是总数。
比如用 show table status, 虽然不准但勉强够用.
比如上缓存, 程序启动时候查一次缓存起来, 业务更新缓存.
3. 改需求,不要 count 全表。比如后台的管理列表的分页, 就可以只查询前 10W 条,其他情况下带精确的查询条件时再解除限制。
seers

seers      5 小时 41 分钟前 via Android

v2eb

v2eb      5 小时 40 分钟前 via Android

看看表结构
encro

encro      5 小时 40 分钟前

navicat 的统计自动走了统计表,不是准确的。

count 是必须准确的,而且是需要考虑脏数据。
fengpan567

fengpan567      5 小时 39 分钟前

explain select count(id) from table_name; 看看用的什么索引,索引长度是多少
encro

encro      5 小时 31 分钟前

关系数据库几个很多无法解决的问题:

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

以上等等限制才会有 es,mongo,hbase,redis,InfluxDB,GDB 等等的机会。以上导致关系数据库没有走主键索引的话也就千万级别数据量比较合适吧。如果都是走主键那随便放。
PythonYXY

PythonYXY      5 小时 20 分钟前

你把两个 sql 的执行过程贴出来
luozic

luozic      5 小时 20 分钟前

看执行计划,时间花在哪了。。。
hhjswf

hhjswf      5 小时 14 分钟前 via Android

我寻思 count 可不就必须全盘扫描了,还搁着索引呢。。有用吗
hhjswf

hhjswf      5 小时 3 分钟前 via Android

应该是 count 用了临时表
shore123

shore123      5 小时 2 分钟前

因为你 SELECT id FROM table_name; 这条查询的是第一页吧....
netnr

netnr      4 小时 49 分钟前 via Android

还有一种可能,都慢,第一种方式走缓存了
akira

akira      3 小时 4 分钟前

navicat 会自动加 limit ,所以你前面那个是秒出。
littlewing

littlewing      2 小时 52 分钟前

SELECT id FROM table_name;--一秒钟出结果,我的表大概三十万数据
select count(id) from table_name;--超过二十秒

不可能,不科学,SELECT id FROM table_name 也是把 30 万条数据每一条都查出来,怎么可能差别那么大

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK