[分享]MySQL中分页的优化_MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2181 | 回复: 0   主题: [分享]MySQL中分页的优化        下一篇 
unknsnow
注册用户
等级:上士
经验:272
发帖:78
精华:0
注册:2012-2-10
状态:离线
发送短消息息给unknsnow 加好友    发送短消息息给unknsnow 发消息
发表于: IP:您无权察看 2014-11-7 10:26:55 | [全部帖] [楼主帖] 楼主

关于分页的优化。
我们知道,在 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)


--转自 北京联动北方科技有限公司




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论