V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wxsm
V2EX  ›  程序员

分页查询,查个 total 很难吗?

  •  
  •   wxsm ·
    wxsms · 2018-04-02 10:42:22 +08:00 · 14449 次点击
    这是一个创建于 2412 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题。一个破接口,后端开发人员三番五次说要不传 total,让我去别的地方取,说什么查个 total 相当全表扫,我真是服气。

    第 1 条附言  ·  2018-04-02 18:55:21 +08:00

    认真阅读了各位的回复,感谢。

    1. 我自己确实不是专业后端开发者,知识有限,才会问出这个问题。
    2. 场景是:评论查询,app端展示,需要展示个总评论总数。
    3. 最后我们经过了友好的交流,索引+缓存足以解决问题(实时性需求不是很高)
    95 条回复    2018-08-24 14:55:45 +08:00
    GaryZ
        1
    GaryZ  
       2018-04-02 12:31:35 +08:00
    他不会建索引么 你去别的地方取 去哪取 去他家么?
    kunluanbudang
        2
    kunluanbudang  
       2018-04-02 12:34:18 +08:00 via Android
    后端水平不行

    楼主可以继续怼他
    finab
        3
    finab  
       2018-04-02 12:35:51 +08:00
    √ 和他讲清楚,并提供相关文档给他查询 问题解决
    × 上 V 站抱怨 毫无用处
    sagaxu
        4
    sagaxu  
       2018-04-02 12:37:58 +08:00 via Android
    数据量大时查 total 是很慢的,不带条件 count 一次主键几十秒很正常
    q364553873
        5
    q364553873  
       2018-04-02 12:38:33 +08:00 via Android
    lz count 一个千万级的表试试。。
    banks0913
        6
    banks0913  
       2018-04-02 12:42:49 +08:00
    @q364553873 新人求学习。那这种情况一般有什么样的解决方案?
    notreami
        7
    notreami  
       2018-04-02 12:44:41 +08:00
    数据库性能都严重影响了,为啥不上 ES 呢?
    annielong
        8
    annielong  
       2018-04-02 12:45:56 +08:00
    大数据按条件分页查询再带 count 真的很麻烦,尤其是条件复杂的时候,优化都不好优化,只能跑两次查询,还特别慢
    kera0a
        9
    kera0a  
       2018-04-02 12:46:24 +08:00
    @banks0913 我记得 MySQL 是有优化的,单纯的 count(*) 应该不是全表,速度很快的
    GoLand
        10
    GoLand  
       2018-04-02 12:47:09 +08:00
    后端说的没毛病,能不用尽量不用 total。前端不用考虑啥性能问题,但是后端要考虑。
    sagaxu
        11
    sagaxu  
       2018-04-02 12:48:50 +08:00 via Android
    @kera0a 那是古代的 myisam 引擎,现代关系型 db,count 都很慢
    neop
        12
    neop  
       2018-04-02 12:52:30 +08:00 via iPhone
    话说前端去哪里取 total
    sxlzll
        13
    sxlzll  
       2018-04-02 13:02:53 +08:00   ❤️ 1
    1、可能很难,不了解数据量和存储不做评价
    2、楼主是前端,只需要站在用户和前端的角度思考,total 是不是必须的,如果是,后端就必须做,至于难的问题,什么事都那么简单那还要我们工程师干嘛
    EmdeBoas
        14
    EmdeBoas  
       2018-04-02 13:03:56 +08:00
    最近也是碰到了这个问题....5000W 的表...不带条件查 total 报警了....最后用 kylin 解决了,美滋滋
    winglight2016
        15
    winglight2016  
       2018-04-02 13:08:03 +08:00
    @EmdeBoas kylin,这个之前我也想用,但是没找到合适的场景,大佬再深入讲讲?
    brickyang
        16
    brickyang  
       2018-04-02 13:08:13 +08:00 via iPhone   ❤️ 1
    @banks0913 #6 可以维护一个字段,跟随增删 +/-1
    lishunli
        17
    lishunli  
       2018-04-02 13:09:54 +08:00 via Android
    带 total 又要多查一次 db,要考虑量大性能问题什么。有总数就有可能查到最后一页,量大的话数据库查询最后几页还是很慢的。当然前提是数据多,如果就很少那无所谓了。
    binux
        18
    binux  
       2018-04-02 13:12:21 +08:00 via Android
    这问题你去问 PM 啊,PM 说要做就做。
    然后再让 PM 找后端 estimate story points,看 PM 乐意给排期不。
    你操这个心干嘛。
    hcymk2
        19
    hcymk2  
       2018-04-02 13:13:26 +08:00
    @brickyang
    对有查询条件的这个字段有用么?
    nigelvon
        20
    nigelvon  
       2018-04-02 13:15:35 +08:00   ❤️ 1
    不会做缓存?楼上说慢的我真是醉了,每次取数据都 count 一遍?
    EmdeBoas
        21
    EmdeBoas  
       2018-04-02 13:17:34 +08:00
    @winglight2016 kylin 就是做预计算的,支持百亿级数据查询毫秒出结果...一般查历史数据的时候好用,比如说今天 4-2 号,你只需要查 4-1 号以及之前的数据,就比较适用,每天写个定时任务,增量把前一天的数据预计算好给第二天用。kylin 搭起来跟维护的成本相当大的...
    EmdeBoas
        22
    EmdeBoas  
       2018-04-02 13:18:17 +08:00
    @nigelvon 然而查询条件会变,数据的量也可能在变
    VincentWang
        23
    VincentWang  
       2018-04-02 13:20:35 +08:00   ❤️ 1
    @nigelvon 不太好缓存吧,即使不考虑数据库里的数据量在变化,查询条件也会变。
    nigelvon
        24
    nigelvon  
       2018-04-02 13:20:49 +08:00
    @EmdeBoas 数据变更不会更新缓存?查询条件组合多不会多设置几条缓存组合?
    恕我直言,连 total 都不愿意给的后端我不信数据多到 count 都慢的程度
    linbiaye
        25
    linbiaye  
       2018-04-02 13:20:50 +08:00   ❤️ 1
    如果是 Mysql 的 InnoDB 的 count 不带 where 就是全表扫描,带了 where 看具体的 where,所以后端说的没毛病,表大了没有利用好索引或者没法利用索引就是很慢。
    abusizhishen
        26
    abusizhishen  
       2018-04-02 13:22:32 +08:00 via Android
    他可以对指定来源屏蔽这个参数
    EmdeBoas
        27
    EmdeBoas  
       2018-04-02 13:23:02 +08:00
    @nigelvon .....我最近做的查询条件组合起来可能有上万种....做 count 多 9 秒起...
    sagaxu
        28
    sagaxu  
       2018-04-02 13:27:12 +08:00 via Android
    @nigelvon 查询条件的组合,数量是乘起来的,超过几十个的时候,更新缓存的成本会很高
    nigelvon
        29
    nigelvon  
       2018-04-02 13:28:15 +08:00
    @EmdeBoas 你这根本就不光是 count 的问题,连数据都查不出来,上搜索引擎。从楼主描述来看取数据没问题,那么 count 不存在简单方案解决不了的性能问题。
    scnace
        30
    scnace  
       2018-04-02 13:32:00 +08:00 via Android
    实时数据的 Count 真的很麻烦(耗性能) 分页那种 Case 的话 可以把 Total 拉到比较大 或者 同意楼上的维护单独表 count 的做法(鸟书也推荐这么做) P.S. es 并不是银弹 也要考虑到多个数据源的维护成本
    eslizn
        31
    eslizn  
       2018-04-02 13:34:33 +08:00
    @nigelvon 取数据没问题不代表 count 没问题
    EmdeBoas
        32
    EmdeBoas  
       2018-04-02 13:34:44 +08:00   ❤️ 3
    @nigelvon 老哥,你这根本不讲道理,你又不知道实际情况,你以为想用搜索引擎就用?都得结合自己组有的资源,解决方法有一万种,但更重要的是资源复用和可维护性
    whypool
        33
    whypool  
       2018-04-02 13:35:59 +08:00
    话说,数据量多的时候存自增 id,拿 max 会不会快点?
    debuggerx
        34
    debuggerx  
       2018-04-02 13:36:27 +08:00
    上个项目里有个查询,数据量大概在 300W 左右,每次都查出 count 的话还是比较影响性能的,查询一般在 1~3 秒,但是分析下来这个接口是一个下滑展示,而且没有提供转跳到某一页的功能,也就是说有用户死命地不停滑动也要一天才会请求到最后的数据,于是我专门给这个接口写了个分页查询,total 从 redis 里取,redis 里的值只在每天凌晨更新一次……
    startar
        35
    startar  
       2018-04-02 13:38:26 +08:00 via Android
    如果后端是单纯的 db 的话,实时查 count 确实有可能很慢啊。一般都要扫索引。如果真要实时查就得预计算,上 kylin。
    建议对自己不熟悉的领域不要那么想当然。。
    Socket
        36
    Socket  
       2018-04-02 13:41:40 +08:00
    似曾相识,这玩意儿没 total 可不行,panigation 这种组件不传 total 没法展示页码,你只能点一下查一下,有就展示,没有就展示没数据
    cheetah
        37
    cheetah  
       2018-04-02 13:47:46 +08:00
    哈哈看看豆瓣广播现在也没总页数
    arslion
        38
    arslion  
       2018-04-02 13:49:20 +08:00
    不讲清楚场景发这帖子干嘛?
    wangbenjun5
        39
    wangbenjun5  
       2018-04-02 13:49:22 +08:00
    说实话,那种几百上千万的数据表你们分页是给人看的吗?
    wwdyy
        40
    wwdyy  
       2018-04-02 13:51:27 +08:00
    那就跟产品说,后端说做不了分页,只能做下一页这样的
    killerv
        41
    killerv  
       2018-04-02 13:53:44 +08:00
    InnoDB 引擎的大表 count 确实慢,可以考虑缓存 count,插入和删除行的时候实时更新缓存。
    nszm
        42
    nszm  
       2018-04-02 13:53:53 +08:00
    @whypool #33 有个搜索条件
    slime7
        43
    slime7  
       2018-04-02 13:55:37 +08:00
    某绿帽论坛的查询会显示灰色页码,tooltip 提示可能有 xx 页,直到点到某页后没数据
    ty89
        44
    ty89  
       2018-04-02 13:57:36 +08:00
    不好说,这个得看业务情况具体分析,不过多数情况下用假分页就行了,比如微博的 timeline,不可能给你算 total 的
    hadixlin
        45
    hadixlin  
       2018-04-02 14:11:37 +08:00 via iPhone
    楼主的基础知识薄弱呀,这个 count 的问题可能是很复杂的优化,考虑成本来说,一般都是不做的
    logOo
        46
    logOo  
       2018-04-02 14:18:34 +08:00
    @wangbenjun5 嗯,你这个思路很好。
    jadec0der
        47
    jadec0der  
       2018-04-02 14:21:02 +08:00
    笑~很多时候前端开发表现的像普通用户一样。

    不知道你是多大的数据量,数据量大了以后 total 确实很难取,很多场景都是估算或者只给前面一部分结果,比如 Google 搜索,result 数量是估算的,翻页一般也只能翻几十页
    panlilu
        48
    panlilu  
       2018-04-02 14:22:49 +08:00
    数据量大的情况查 total 是挺难的……
    3a3Mp112
        49
    3a3Mp112  
       2018-04-02 14:24:13 +08:00
    根本没说清楚这个 total 指的是什么数据,是每次请求回来的有效数量,还是什么?
    w0000
        50
    w0000  
       2018-04-02 14:28:08 +08:00
    数据大,有 where 条件,条件多并且组合也多的时候,是快不了的啊楼主
    Immortal
        51
    Immortal  
       2018-04-02 14:28:13 +08:00
    其实看完描述我有几个问题和想法
    1、从别的地方取是哪里取?如果他这个接口里不好传,别的地方就能传了?
    2、这个应该不是全表扫,会走主键索引应该,都不会回表才是

    结果和楼上们说的一样,得看数据量才能决定,不是百万千万的 count 还是很快的,如果有连续主键都不用 count,取最大自增主键就好。以前我也经常和客户端吵这类问题,因为我发现他们没法理解服务端需要考虑的问题。归根结底还是没好好沟通,两边都有点责任,抽个时间和服务端聊下解决方案好了。具体服务端的优化方式楼上很多了。
    MushishiXian
        52
    MushishiXian  
       2018-04-02 14:38:15 +08:00
    有时候 count 真的会挺慢的,加缓存你又要考虑各种查询条件,如果这个 total 不是特别重要,就真的没必要去 count
    jydeng
        53
    jydeng  
       2018-04-02 14:40:26 +08:00
    total 确实很复杂,我们现在表数据量小的话,一般查询两次,一次查 total,一次分页查具体数据。
    iyaozhen
        54
    iyaozhen  
       2018-04-02 14:47:32 +08:00 via Android
    抛开数据量和场景都是耍流氓
    vincenttone
        55
    vincenttone  
       2018-04-02 14:55:29 +08:00
    - 如果数据量大做了分表,恐怕后端就需要做个计数器(还不一定保证准确)。
    - 如果数据量小不做分表,多一次 IO。可以不扫全表,前提是有可用的索引。
    sm0king
        56
    sm0king  
       2018-04-02 15:04:00 +08:00
    不管什么原因,该一个请求返回过来的数据,非要请求两条,还有,丢过来一堆数据让前端自己做数据处理对接的后台,都是偷懒。
    play78
        57
    play78  
       2018-04-02 15:07:51 +08:00
    这个还是要根据实际业务来, 如果是必须的,那就提供呗。客户能接收等待时间,就多等几秒。
    如果业务中,不是必须的,就不用了。
    例如,查询记录类的数据。只要告诉用户有下一页就可以。不用提供总共有多少页。让用户一直下一页,下一页。
    又比如,一些动态排名之类的。可以后端起个定时任务,每 10 分钟更新一次数据。
    如果是要求实时类的,比如一些余额。那就必须要每次都统计了。
    JamesPan
        58
    JamesPan  
       2018-04-02 15:18:25 +08:00
    @kera0a myisam count 很快,innodb count 真的是扫全表,可以用 explain 得到的影响行来大致顶替 count
    glues
        59
    glues  
       2018-04-02 15:22:22 +08:00
    ls 的某些高手很多啊,吹牛不要钱是吗?
    Sunshow
        60
    Sunshow  
       2018-04-02 15:52:14 +08:00
    是很难,没必要最好别用
    weizhen199
        61
    weizhen199  
       2018-04-02 15:53:48 +08:00
    有个办法,去统计信息里拿总行数,大致是精准的
    toono
        62
    toono  
       2018-04-02 16:06:03 +08:00
    内心 OS: 他到底在说 MySQL 还是 MongoDB.....
    tulongtou
        63
    tulongtou  
       2018-04-02 16:08:15 +08:00
    @kera0a 问题是你不知道 where 后面有什么条件呢,所以没办法说 count(*) 快慢
    tairan2006
        64
    tairan2006  
       2018-04-02 16:12:38 +08:00
    真太大了就用 es/solr 查…
    RTNelo
        65
    RTNelo  
       2018-04-02 16:17:59 +08:00
    还好在我司没遇到过大表显示页号的需求,给前端传个 `is_end` 就行了
    Immortal
        66
    Immortal  
       2018-04-02 16:19:15 +08:00
    @weizhen199
    这个的确可以,innodb 的查询优化器里应该有个大概数据用来做优化推算
    chenqh
        67
    chenqh  
       2018-04-02 16:27:17 +08:00
    @weizhen199 不会拿。。
    barbery
        68
    barbery  
       2018-04-02 16:37:58 +08:00
    很烦这种分页,最完美的分页就是游标(逃
    cysroad
        69
    cysroad  
       2018-04-02 16:38:00 +08:00
    如果一个表几百万的数据,一页 20 条,你显示个总页数有意思吗?分页带 total,一般只做 50 页以内的
    kimmykuang
        70
    kimmykuang  
       2018-04-02 16:38:08 +08:00
    这个不是量大了都会遇到的问题么,简单就是做异构索引上 es,mysql innodb 千万各种条件 count,给个完美的方案?
    icegreen
        71
    icegreen  
       2018-04-02 16:51:48 +08:00
    应该传 / 后端不行
    icegreen
        72
    icegreen  
       2018-04-02 16:55:53 +08:00
    这种肯定是从用户 /产品设计的角度去出发, 第一要考虑的肯定是用户的体验和满足产品的需求;

    另外接口设计肯定是要为使用者服务和考虑的, 至少我们是这样要求的.
    JKeita
        73
    JKeita  
       2018-04-02 17:05:41 +08:00
    不管你建不建索引,只要命中的数据量很大时,查 total 本来就很慢
    finull
        74
    finull  
       2018-04-02 17:07:58 +08:00
    @debuggerx 这种不需要 total,某页如果是满页就认为有下一页就好
    RubyJack
        75
    RubyJack  
       2018-04-02 17:09:54 +08:00
    你看看淘宝网给不给你翻到最后一页?
    count 就是性能杀手,能不做就不做,后端没毛病。
    wengjin456123
        76
    wengjin456123  
       2018-04-02 17:11:57 +08:00
    楼主没毛病啊,total 当然要给啊
    nxtxiaolong
        77
    nxtxiaolong  
       2018-04-02 17:12:11 +08:00
    这个看数据库本身表中有没有存这个字段了,比如 mongodb 就每隔 collection 有这样的字段,没啥大问题,如果涉及到全表扫面,建立索引也是很慢的~
    JKeita
        78
    JKeita  
       2018-04-02 17:12:12 +08:00
    数据量大就用 ES,才比较好解决
    JKeita
        79
    JKeita  
       2018-04-02 17:15:03 +08:00
    还有即使是 ES 也会限制页数,页数越大查询越慢。所以数据量很大时,传 total 根本就毫无意义
    maemual
        80
    maemual  
       2018-04-02 17:21:54 +08:00
    如上面所说,我们不知道你们的业务场景到底是什么,上面动不动随便让人用 ES 的也都是随便瞎说。只能说的是,在某些场景下,取 count 可能确实是一个很麻烦的事情。所以希望能够对后端更加宽容,去了解为什么之后,好好的沟通。
    jason19659
        81
    jason19659  
       2018-04-02 17:30:07 +08:00
    所以百万级的数据展示准确的 total 有什么意义。。数据少直接 count
    dishuibaby
        82
    dishuibaby  
       2018-04-02 17:47:15 +08:00
    我们数据量比较大的时候。就用 solr 查询了。
    还有就是给前端用户的展现。通常展现的都固定条件的列表,也不需要展现所有的数据列表吧。应该也不会有很复杂的搜索让用户自己选择。如果查询条件真的复杂了,那就要借助其他工具了。solr es xunsearch 都可以把
    如果只是用 mysql 查,我们通常做的是最多展现 1000 页。
    aliasliyu4
        83
    aliasliyu4  
       2018-04-02 18:01:43 +08:00 via iPhone
    数据量很大的时候,我真的做不到啊,您继续喷吧,或者您来?
    chairuosen
        84
    chairuosen  
       2018-04-02 18:19:11 +08:00
    海量数据不是给人看的,给人看的拿 100 页足够
    LichMscy
        85
    LichMscy  
       2018-04-02 18:25:34 +08:00
    哈哈看标题第一反应没建索引,点进来果然
    adablue77
        86
    adablue77  
       2018-04-02 18:48:28 +08:00
    如果你是前端 要明白自己职责是展现数据
    数据都不给你 展现个毛线啊
    性能优化不是你需要考虑的范围
    产品原型确实需要 total 值 就跟写接口的要去
    如果真是百万千万级的分页 你们后端会找产品撕逼的 不用你管
    以性能推脱 不给数据 那直接出静态页多好 保证快
    jjx
        87
    jjx  
       2018-04-02 19:00:23 +08:00
    搞 erp 的哭了


    每次报表必须有小计合计, 怎么也逃不过查询理论上执行了两次的命运
    woshifyz
        88
    woshifyz  
       2018-04-02 19:10:24 +08:00
    @nigelvon 你真写过大数据量的 count 吗?
    yiplee
        89
    yiplee  
       2018-04-02 19:23:46 +08:00
    展示总评论总数查询条件不复杂性能肯定没问题
    liuxu
        90
    liuxu  
       2018-04-02 19:36:22 +08:00
    需要建汇总表,《高性能 mysql 》一书建议可以用 Flexviews 插件
    projectzoo
        91
    projectzoo  
       2018-04-02 19:38:37 +08:00
    这个 count 确实不是简单的 count。。。
    一个 comment 表中查询某一条 news 的 comment count 真的不是简单得 select count(*) 这么搞。
    jyf
        92
    jyf  
       2018-04-03 10:04:24 +08:00
    count 确实慢 不过不给是不对的 我就是做后端的 后端不应该把自己的技术困难推给调用方 如果真的很慢 那就上缓存 告知不能达到很高实时性就可以了
    petelin
        93
    petelin  
       2018-04-03 10:31:30 +08:00
    700 万 700MB, 花了 1.59 秒
    6000 万 2.3G, count 不出来(已经没耐心等待返回了)
    winglight2016
        94
    winglight2016  
       2018-04-10 19:17:12 +08:00
    @EmdeBoas 那我是没机会用了,小厂完全用不上
    Jamy
        95
    Jamy  
       2018-08-24 14:55:45 +08:00
    @LichMscy 85 我的 mongodb 中的一个集合光索引大小就 50G, 带条件 count??不存在的.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2754 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 14:51 · PVG 22:51 · LAX 06:51 · JFK 09:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.