分页查询,你真的懂吗?

程序员代码的编写能力主要体现在思维的严谨上。有些看起来很简单的东西,里面包含很多很细的点,你能想到吗?今天我就简单说一下一个例子,让大家学习到新知识的同时,也养成一种思维的习惯。

有一张收藏表,里面存储的是用户和图书ID。数据量为1亿。现在要求分页获取所有用户ID(不重复),写下你的sql语句。

表结构大致如下:

三种设计

最容易想到的第一种分页语句是(这也是我们最容易想到的语句):

再高级点语句,第二种($last_min_uid表示上一次读到的最后一个uid):

最高级的方式

分析

以上三种方式都可以实现分页获取到用户ID列表,那么区别是什么?我现在就把每一种跟大家分析下。

第一种在业务场景中,会出现丢数据的情况。——这是比较严重的情况,不予采纳。

具体的业务场景是这样的:当你读取第5页的时候,前四页的用户id列表中,假如有一页的用户ID从库中删除掉,那么你这时读到的第5页(limit 51, 10),就是原来的第6页,你会把1页的用户ID丢失掉。

第二种的第二条语句,通过explain分析,实际并没有命中唯一索引,而只是命中了一般索引,数据查询范围在7百万级别,故explain建议我们使用group by。——这个查询会有严重的性能问题。

第三种explain分析,数据查询范围在12万级别(跟第二种相差一个数量级),查询性能高。

2 14 收藏 11 评论

相关文章

可能感兴趣的话题



直接登录
最新评论
  • 鲨灬漏   2015/10/22

    第一种情况并不会导致数据丢失的情况。limit的是索引,而不是键值,所以就算删除了数据也不会出现混乱的情况。。。第二种的大数据下命中索引,从而提高性能的思路倒是可以借鉴。

    • 悟空 java服务器开发 2015/10/23

      会丢失数据的。。。,好好想想

      • 鲨灬漏   2015/10/24

        测试过呀,没有丢失。
        limit 0, 10; limit 11, 10; 其中的 0, 11不是主键id 的值,而是数据在数据库中的顺序,比如 id=2的数据,可能是放在第一位的。 所以 limit 0,1 会筛选出 id=2 的数据,而不是 空 。

        我就是这么想的, 有什么问题么?请问,谢谢。

        • 天然 开发工程师 2015/10/24

          首先limit后面跟的是数据的起始位置,不是主键的索引. limit 0,10 就是从开头向后读取10行。假设表里有30条记录 读取3次 并不存在丢失数据的情况 不知道楼主是什么样的情景会丢失数据

          • 鲨灬漏   2015/10/26

            只能理解成博主的表达,和我们的理解不一样了。肯定是表述有问题,去粗取精,不要在意那些不必要的细节。

            • 悟空 java服务器开发 2015/10/27

              场景是这样的,你先查十条记录,这时另一个线程删除了一条记录,这条记录其实在前十个里的
              你在从11开始查询,是不是丢失数据了?不可重复读。

              • 鲨灬漏   2015/10/27

                还是表述的问题,如果表述成:分批次,每次10个,将所有数据读取出。。这样的业务需求的话,就不能简单的limit 10每次了。

                但是作为分页的话,就是把整个页数 / 每次呈现数 ,在前面删除了一个数据的话,会有后面的补上,总是要凑足 每次呈现数的,不存在丢失数据的说法。不过limit这种特性,还是要注意小心为好,想当然的就可能用错。

  • aaron 程序猿 2015/10/23

    后两种的查询效率是比第一种要高,而且不会出现数据混乱的情况,但是每次请求过来,我们得知道上一次请求的最后一条数据的uid,这个在哪记录?

  • 为什么放到group by后就能命中唯一索引了?

跳到底部
返回顶部