zoukankan      html  css  js  c++  java
  • MySQL的分页的优化

    关于分页的优化。
    我们知道,在MySQL中分页很简单,直接LIMIT page_no,page_total 就可以了。
    可是当记录数慢慢增大时,她就不那么好使了。
    这里我们创建摘要表来记录页码和原表之间的关联。
    下面为测试数据。

    原表:
    CREATE TABLE `t_group` (
      `id` int(11) NOT NULL auto_increment,
      `money` decimal(10,2) NOT NULL,
      `user_name` varchar(20) NOT NULL,
      `create_time` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
      PRIMARY KEY  (`id`),
      KEY `idx_combination1` (`user_name`,`money`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    原表总记录数:
    mysql> select count(*) from t_group;
    +----------+
    | count(*) |
    +----------+
    | 10485760 |
    +----------+
    1 row in set (0.00 sec)
    分页表:


    CREATE TABLE `t_group_ids` (
      `id` int(11) NOT NULL,
      `group_id` int(11) NOT NULL,
      PRIMARY KEY  (`id`,`group_id`),
      KEY `idx_id` (`id`),
      KEY `idx_group_id` (`group_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


    插入分页表数据。当然这里如果你的表主键不是ID,那你得自己想办法搞这个分页表的数据了。这个好实现,就不说了。
    mysql> insert into t_group_ids select ceil(id/20),id from t_group;
    Query OK, 10485760 rows affected (2 min 56.19 sec)
    Records: 10485760  Duplicates: 0  Warnings: 0

    现在来看看对比数据。

    用普通LIMIT来实现分页。

    mysql> select * from t_group where 1 limit 20;
    +----+--------+-----------+---------------------+
    | id | money  | user_name | create_time         |
    +----+--------+-----------+---------------------+
    |  1 |  50.23 | david     | 2008-10-23 12:55:49 |
    |  2 |  55.23 | livia     | 2008-10-23 10:02:09 |
    |  3 | 100.83 | leo       | 2008-10-23 10:02:22 |
    |  4 |  99.99 | lucy      | 2008-10-23 10:02:39 |
    |  5 | 299.99 | simon     | 2008-10-23 10:02:52 |
    |  6 | 599.99 | sony      | 2008-10-23 10:03:03 |
    |  7 | 599.99 | rick      | 2008-10-23 10:03:12 |
    |  8 |   9.99 | anne      | 2008-10-23 10:03:47 |
    |  9 |   9.99 | sarah     | 2008-10-23 10:04:31 |
    | 10 | 900.99 | john      | 2008-10-23 10:04:50 |
    | 11 |   0.23 | david     | 2008-10-23 10:05:31 |
    | 12 |   5.23 | livia     | 2008-10-23 10:05:31 |
    | 13 |  50.83 | leo       | 2008-10-23 10:05:31 |
    | 14 |  49.99 | lucy      | 2008-10-23 10:05:31 |
    | 15 | 249.99 | simon     | 2008-10-23 10:05:31 |
    | 16 | 549.99 | sony      | 2008-10-23 10:05:31 |
    | 17 | 549.99 | rick      | 2008-10-23 10:05:31 |
    | 18 | -40.01 | anne      | 2008-10-23 10:05:31 |
    | 19 | -40.01 | sarah     | 2008-10-23 10:05:31 |
    | 20 | 850.99 | john      | 2008-10-23 10:05:31 |
    +----+--------+-----------+---------------------+
    20 rows in set (0.01 sec)


    用分页表来实现分页。

    mysql> select a.* from t_group as a inner join t_group_ids as b where a.id = b.g
    roup_id and b.id = 1;
    +----+--------+-----------+---------------------+
    | id | money  | user_name | create_time         |
    +----+--------+-----------+---------------------+
    |  1 |  50.23 | david     | 2008-10-23 12:55:49 |
    |  2 |  55.23 | livia     | 2008-10-23 10:02:09 |
    |  3 | 100.83 | leo       | 2008-10-23 10:02:22 |
    |  4 |  99.99 | lucy      | 2008-10-23 10:02:39 |
    |  5 | 299.99 | simon     | 2008-10-23 10:02:52 |
    |  6 | 599.99 | sony      | 2008-10-23 10:03:03 |
    |  7 | 599.99 | rick      | 2008-10-23 10:03:12 |
    |  8 |   9.99 | anne      | 2008-10-23 10:03:47 |
    |  9 |   9.99 | sarah     | 2008-10-23 10:04:31 |
    | 10 | 900.99 | john      | 2008-10-23 10:04:50 |
    | 11 |   0.23 | david     | 2008-10-23 10:05:31 |
    | 12 |   5.23 | livia     | 2008-10-23 10:05:31 |
    | 13 |  50.83 | leo       | 2008-10-23 10:05:31 |
    | 14 |  49.99 | lucy      | 2008-10-23 10:05:31 |
    | 15 | 249.99 | simon     | 2008-10-23 10:05:31 |
    | 16 | 549.99 | sony      | 2008-10-23 10:05:31 |
    | 17 | 549.99 | rick      | 2008-10-23 10:05:31 |
    | 18 | -40.01 | anne      | 2008-10-23 10:05:31 |
    | 19 | -40.01 | sarah     | 2008-10-23 10:05:31 |
    | 20 | 850.99 | john      | 2008-10-23 10:05:31 |
    +----+--------+-----------+---------------------+
    20 rows in set (0.00 sec)



    取第50W页的数据。
    原来表:

    mysql> select * from t_group where 1 limit 9999980,20;
    +----------+---------+-----------+---------------------+
    | id       | money   | user_name | create_time         |
    +----------+---------+-----------+---------------------+
    |  9999981 |  810.13 | david     | 2008-10-23 10:09:24 |
    |  9999982 |  815.13 | livia     | 2008-10-23 10:09:24 |
    |  9999983 |  860.73 | leo       | 2008-10-23 10:09:24 |
    |  9999984 |  859.89 | lucy      | 2008-10-23 10:09:24 |
    |  9999985 | 1059.89 | simon     | 2008-10-23 10:09:24 |
    |  9999986 | 1359.89 | sony      | 2008-10-23 10:09:24 |
    |  9999987 | 1359.89 | rick      | 2008-10-23 10:09:24 |
    |  9999988 |  769.89 | anne      | 2008-10-23 10:09:24 |
    |  9999989 |  769.89 | sarah     | 2008-10-23 10:09:24 |
    |  9999990 | 1660.89 | john      | 2008-10-23 10:09:24 |
    |  9999991 |  760.13 | david     | 2008-10-23 10:09:24 |
    |  9999992 |  765.13 | livia     | 2008-10-23 10:09:24 |
    |  9999993 |  810.73 | leo       | 2008-10-23 10:09:24 |
    |  9999994 |  809.89 | lucy      | 2008-10-23 10:09:24 |
    |  9999995 | 1009.89 | simon     | 2008-10-23 10:09:24 |
    |  9999996 | 1309.89 | sony      | 2008-10-23 10:09:24 |
    |  9999997 | 1309.89 | rick      | 2008-10-23 10:09:24 |
    |  9999998 |  719.89 | anne      | 2008-10-23 10:09:24 |
    |  9999999 |  719.89 | sarah     | 2008-10-23 10:09:24 |
    | 10000000 | 1610.89 | john      | 2008-10-23 10:09:24 |
    +----------+---------+-----------+---------------------+
    20 rows in set (4.21 sec)

    分页表:

    mysql> select a.* from t_group as a inner join t_group_ids as b where a.id = b.g
    roup_id and b.id = 500000;
    +----------+---------+-----------+---------------------+
    | id       | money   | user_name | create_time         |
    +----------+---------+-----------+---------------------+
    |  9999981 |  810.13 | david     | 2008-10-23 10:09:24 |
    |  9999982 |  815.13 | livia     | 2008-10-23 10:09:24 |
    |  9999983 |  860.73 | leo       | 2008-10-23 10:09:24 |
    |  9999984 |  859.89 | lucy      | 2008-10-23 10:09:24 |
    |  9999985 | 1059.89 | simon     | 2008-10-23 10:09:24 |
    |  9999986 | 1359.89 | sony      | 2008-10-23 10:09:24 |
    |  9999987 | 1359.89 | rick      | 2008-10-23 10:09:24 |
    |  9999988 |  769.89 | anne      | 2008-10-23 10:09:24 |
    |  9999989 |  769.89 | sarah     | 2008-10-23 10:09:24 |
    |  9999990 | 1660.89 | john      | 2008-10-23 10:09:24 |
    |  9999991 |  760.13 | david     | 2008-10-23 10:09:24 |
    |  9999992 |  765.13 | livia     | 2008-10-23 10:09:24 |
    |  9999993 |  810.73 | leo       | 2008-10-23 10:09:24 |
    |  9999994 |  809.89 | lucy      | 2008-10-23 10:09:24 |
    |  9999995 | 1009.89 | simon     | 2008-10-23 10:09:24 |
    |  9999996 | 1309.89 | sony      | 2008-10-23 10:09:24 |
    |  9999997 | 1309.89 | rick      | 2008-10-23 10:09:24 |
    |  9999998 |  719.89 | anne      | 2008-10-23 10:09:24 |
    |  9999999 |  719.89 | sarah     | 2008-10-23 10:09:24 |
    | 10000000 | 1610.89 | john      | 2008-10-23 10:09:24 |
    +----------+---------+-----------+---------------------+
    20 rows in set (0.03 sec)


    我们来取最后一页的数据。
    原表:


    mysql> select * from t_group where 1 limit 10485740,20;
    +----------+---------+-----------+---------------------+
    | id       | money   | user_name | create_time         |
    +----------+---------+-----------+---------------------+
    | 10485741 | 1935.42 | david     | 2008-10-23 10:09:24 |
    | 10485742 | 1955.42 | livia     | 2008-10-23 10:09:24 |
    | 10485743 | 2137.82 | leo       | 2008-10-23 10:09:24 |
    | 10485744 | 2134.46 | lucy      | 2008-10-23 10:09:24 |
    | 10485745 | 2934.46 | simon     | 2008-10-23 10:09:24 |
    | 10485746 | 4134.46 | sony      | 2008-10-23 10:09:24 |
    | 10485747 | 4134.46 | rick      | 2008-10-23 10:09:24 |
    | 10485748 | 1774.46 | anne      | 2008-10-23 10:09:24 |
    | 10485749 | 1774.46 | sarah     | 2008-10-23 10:09:24 |
    | 10485750 | 5338.46 | john      | 2008-10-23 10:09:24 |
    | 10485751 | 1735.42 | david     | 2008-10-23 10:09:24 |
    | 10485752 | 1755.42 | livia     | 2008-10-23 10:09:24 |
    | 10485753 | 1937.82 | leo       | 2008-10-23 10:09:24 |
    | 10485754 | 1934.46 | lucy      | 2008-10-23 10:09:24 |
    | 10485755 | 2734.46 | simon     | 2008-10-23 10:09:24 |
    | 10485756 | 3934.46 | sony      | 2008-10-23 10:09:24 |
    | 10485757 | 3934.46 | rick      | 2008-10-23 10:09:24 |
    | 10485758 | 1574.46 | anne      | 2008-10-23 10:09:24 |
    | 10485759 | 1574.46 | sarah     | 2008-10-23 10:09:24 |
    | 10485760 | 5138.46 | john      | 2008-10-23 10:09:24 |
    +----------+---------+-----------+---------------------+
    20 rows in set (4.88 sec)

    分页表:

    mysql> select a.* from t_group as a inner join t_group_ids as b where a.id = b.g
    roup_id and b.id = 524288;
    +----------+---------+-----------+---------------------+
    | id       | money   | user_name | create_time         |
    +----------+---------+-----------+---------------------+
    | 10485741 | 1935.42 | david     | 2008-10-23 10:09:24 |
    | 10485742 | 1955.42 | livia     | 2008-10-23 10:09:24 |
    | 10485743 | 2137.82 | leo       | 2008-10-23 10:09:24 |
    | 10485744 | 2134.46 | lucy      | 2008-10-23 10:09:24 |
    | 10485745 | 2934.46 | simon     | 2008-10-23 10:09:24 |
    | 10485746 | 4134.46 | sony      | 2008-10-23 10:09:24 |
    | 10485747 | 4134.46 | rick      | 2008-10-23 10:09:24 |
    | 10485748 | 1774.46 | anne      | 2008-10-23 10:09:24 |
    | 10485749 | 1774.46 | sarah     | 2008-10-23 10:09:24 |
    | 10485750 | 5338.46 | john      | 2008-10-23 10:09:24 |
    | 10485751 | 1735.42 | david     | 2008-10-23 10:09:24 |
    | 10485752 | 1755.42 | livia     | 2008-10-23 10:09:24 |
    | 10485753 | 1937.82 | leo       | 2008-10-23 10:09:24 |
    | 10485754 | 1934.46 | lucy      | 2008-10-23 10:09:24 |
    | 10485755 | 2734.46 | simon     | 2008-10-23 10:09:24 |
    | 10485756 | 3934.46 | sony      | 2008-10-23 10:09:24 |
    | 10485757 | 3934.46 | rick      | 2008-10-23 10:09:24 |
    | 10485758 | 1574.46 | anne      | 2008-10-23 10:09:24 |
    | 10485759 | 1574.46 | sarah     | 2008-10-23 10:09:24 |
    | 10485760 | 5138.46 | john      | 2008-10-23 10:09:24 |
    +----------+---------+-----------+---------------------+
    20 rows in set (0.01 sec)


    总结:我们看到,当表记录数增加时,LIMIT的性能随着线性增长。而当我们存放了页码与主键的关联后,性能大增。

  • 相关阅读:
    错误备忘_远程桌面“跟远程计算机的连接被打断。这可能是由网络错误引起的。请重新连接到远程计算机。”
    JavaScript——搞甘特图使用 Date 对象时遇到的问题
    数据结构顺序二叉树
    ASP.NET 用 FlexPaper 在页面上显示 PDF 文件
    数据结构链式二叉树
    ASP.NET 用 Office COM 组件将 docx\pptx\xlsx 转换成 PDF 文件
    开源日志系统比较【转载+整理】
    Oracle 表空间(归档)
    Oracle Bitmap 索引结构、如何存储及其优势
    Bitmap 索引 vs. Btree 索引:如何选择以及何时使用?(归档)
  • 原文地址:https://www.cnblogs.com/secbook/p/2655293.html
Copyright © 2011-2022 走看看