百万级数据分页查询优化方案
死的工作
为了测试下面列出的一些优化,请解释下表。
表格名称:order_history
描述:一个企业的订单历史表
主要研究领域:unsigned int ID字段(4)int类型
现场情况:表包含37个领域,其中不包含大型阵列,如文本,最大为varchar(500),ID字段的索引,并增加。
数据量:5709294
MySQL版本:5.7.16
在线下找到一百万级测试板是不容易的。如果需要自己的测试,可以编写shell脚本的插入数据来测试它。
下列SQL语句的环境不会改变,下面是基本的测试结果:
select count(*)从orders_history;
返回结果:5709294
三次查询如下:
8903毫秒
8323毫秒
8401毫秒
一般的分页查询
一个简单的分页查询可以使用一个简单的限制子句实现:
SELECT * FROM表限排{抵消抵消| }。
限制子句可以用来指定SELECT语句返回的记录数:
第一个参数指定记录行的第一个返回行的偏移量。
第二个参数指定返回记录行的最大行数。
如果只给出一个参数:它表示返回的最大记录数。
第二个参数是1,表示所有记录的检索从一个偏移到记录集的结束
初始记录行的偏移量为0(而不是1)。
下面是一个应用示例:
SELECT * FROM orders_history类型= 8的限制1000,10;
这个语句将查询10件后第一千件从表orders_history,即数据的数据,第一千零一到第一万零一十。
数据表中的记录默认情况下使用主键(一般ID),这与:
SELECT * FROM orders_history类型= 8阶的身份限制10000,10;
三次查询如下:
3040毫秒
3063毫秒
3018毫秒
对于这种类型的查询,以下测试查询记录数量对时间的影响:
SELECT * FROM orders_history类型= 8的限制10000,1;
SELECT * FROM orders_history类型= 8的限制10000,10;
SELECT * FROM orders_history类型= 8限10000100;
SELECT * FROM orders_history类型= 8限100001000;
SELECT * FROM orders_history类型= 8限1000010000;
三个查询时间如下:
1记录查询:3072ms 3092ms 3002ms
10记录查询:3081ms 3077ms 3032ms
100记录查询:3118ms 3200ms 3128ms
1000记录查询:3412ms 3468ms 3394ms
10000记录查询:3749ms 3802ms 3696ms
此外,我还做了十个查询。从查询时间,我们基本上可以确认当查询量小于100时,查询时间没有差别。随着查询记录数量的增加,将花费更多的时间。
查询偏移测试:
SELECT * FROM orders_history类型= 8限100100;
SELECT * FROM orders_history类型= 8限1000100;
SELECT * FROM orders_history类型= 8限10000100;
SELECT * FROM orders_history类型= 8限100000100;
SELECT * FROM orders_history类型= 8限1000000100;
三个查询时间如下:
Query 100 offset: 25ms 24ms 24ms
查询1000:78ms 76ms 77ms偏移
查询10000:3092ms 3212ms 3128ms偏移
查询100000:3878ms 3812ms 3798ms偏移
查询1000000:14608ms 14062ms 14700ms偏移
随着查询偏移量的增加,查询时间急剧增加,特别是查询偏移量大于10万之后。
这个分页查询将从数据库的第一个记录开始扫描,因此查询速度越慢,查询数据越多,查询速度就越慢。
使用子查询优化
这是一种定位偏移位置ID,然后返回的方法,它适用于ID增加的情况。
SELECT * FROM orders_history类型= 8的限制100000,1;
选择ID从orders_history哪里类型= 8的限制100000,1;
SELECT * FROM orders_history类型= 8
ID > =(选择ID从orders_history类型= 8的限制100000,1)
限制100;
SELECT * FROM orders_history类型= 8限100000100;
4语句的查询时间如下所示:
首先声明:3674ms
第二1315ms声明:
第三声明:1327ms
第四声明:3710ms
应该注意上面的查询:
比较第一个语句和第二个语句:使用选择ID而不是选择*的速度增加了3倍。
比较第二个语句和第三个语句:不同速度差的几十毫秒。
比较第三个语句和第四个语句:由于选择ID的速度增加,第三个语句的速度增加了3倍。
这种方法比原始的一般查询方法快几倍。
使用ID限制优化
这样,我们假设数据表的ID不断增加。我们可以根据查询的数量和查询的数量来计算查询ID的范围。我们可以在查询和查询之间使用id。
SELECT * FROM orders_history类型= 2和ID 1000000和1000100限制在100;
查询时间:15ms 12ms 9ms
这种查询方法可以极大地优化查询速度,并且可以在几毫秒内完成。然而,通常在构建表时,会添加基本id字段,这将导致许多遍历到分页查询。
还有另一种写作方式:
SELECT * FROM orders_history其中ID > = 1000001限100;
当然,您也可以使用入到查询的方式,该查询常常用于在多个表连接时查询,并通过使用其他表查询的ID集进行查询。
SELECT * FROM orders_history在ID(选择order_id从trade_2商品=商品=)= 100;
查询中应该注意到:一些MySQL版本不支持子句中的限制用法。
使用临时表优化
这种方式不属于查询优化,这里是一个提及。
为了限制ID优化的使用问题,需要身份证是不断增加的,但在某些情况下,如使用历史表时,或数据丢失的问题,可以考虑使用临时存储表记录ID的页面,使用页面ID查询。这可以大大改善传统的分页查询速度,特别是当数据量上千万。
数据表的id描述
通常,在数据库中设置表时,必须为每个表添加ID增量,这样便于查询。
如果订单像一个数据库,数据非常大,一般都会被分割表,此时不推荐使用数据库的ID作为唯一的标识,但它应该由分布式高并发唯一ID生成器生成,并在数据表中存储另一个独特的字段。
使用第一个范围查询来定位ID(或索引),然后使用索引定位数据,可以提高查询速度几次,即,首先选择ID,然后选择*;