MySQL分页的优化
关于分页的优化。我们知道,在MySQL中分页很简单,直接LIMIT page_no,page_total 就可以了。可是当记录数慢慢增大时,她就不那么好使了。这里我们创建摘要表来记录页码和原表之间的关联。下面为测试数据。
原表:
1、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;
原表总记录数:
1、mysql> select count(*) from t_group;+----------+| count(*) |+----------+| 10485760 |+----------+
分页表:
1、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;
插入分页表数据
1、当然这里如果你的表主键不是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
现在来看看对比数据
1、用普通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)
2、用分页表来实现分页。mysql> select a.* from t_group as a inner join t_group_ids as b where a.id = b.group_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页的数据
1、原来表: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 |+----------+---------+----------
2、分页表:mysql> select a.* from t_group as a inner join t_group_ids as b where a.id = b.group_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)
我们来取最后一页的数据
1、原表:mysql> select * from t_group where 1 l坡纠课柩imit 10485壅酪认奉740,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)
2、分页表:mysql> select a.* from t_group as a inner join t_group_ids as b where a.id = b.group_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)