分类 折腾 下的文章

面对一个百万级别的单表,除了需要合理的表结构设计,还必须对SQL进行精细的优化。以下是对300w数据快速分页查询实例的几种方法对比:

/**
 *  300w数据分页优化
*/
/**
 * mysql的索引对于in语句同样有效,网上说in无法用索引是错误的~
 * 先通过 order by 索引的特性将符合条件的 id 检索出来
 * 再次拼接成 in 条件进行检索 链接没断掉 虽然二次查询但不消耗再次建立链接的资源
 */
$sql = "select sql_no_cache id from sys_data order by id limit 3000020, 10";
$start = microtime(true);
$result = $conn->query($sql);
$id_arr = array_column($result->fetch_all(), 0);
$id_set_str = implode(',', $id_arr);
$sql = "select * from sys_data where id in($id_set_str)";
$result = $conn->query($sql);
$data_1 = $result->fetch_all();
$end = microtime(true);
echo "example_1:";
echo number_format($end - $start, 3) . ' secs' . PHP_EOL;

/**
 * 业界流传的经典方法
 * 通过子查询查处符合条件的 id,取偏移量获得记录
 */
$sql = "select sql_no_cache * from sys_data where id > (select id from sys_data order by id limit 3000020, 1) limit 10";
$start = microtime(true);
$result = $conn->query($sql);
$data_2 = $result->fetch_all();
$end = microtime(true);
echo "example_2:";
echo number_format($end - $start, 3) . ' secs' . PHP_EOL;

/**
 * 普通方法
 * 此类方法针对对数据量比较小的时候还可以应对
 * 数据量十万时可能order by 就无法启用索引了 具体我也没测
 */
$sql = "select sql_no_cache * from sys_data order by id limit 3000020, 10";
$start = microtime(true);
$result = $conn->query($sql);
$data_3 = $result->fetch_all();
$end = microtime(true);
echo "example_3:";
echo number_format($end - $start, 3) . ' secs' . PHP_EOL;

测试结果:

limit 500, 10

example_1:0.006 secs

example_2:0.015 secs

example_3:0.003 secs

limit 5000, 10

example_1:0.004 secs

example_2:0.008 secs

example_3:0.013 secs

limit 50000,10

example_1:0.029 secs

example_2:0.042 secs

example_3:0.109 secs

limit 500000,10

example_1:0.286 secs

example_2:0.346 secs

example_3:4.563 secs

limit 3000000, 10

300w 第一次

example_1:1.356 secs

example_2:1.936 secs

example_3:6.097 secs

300w 第二次

example_1:1.013 secs

example_2:1.534 secs

example_3:6.306 secs

300w 第三次

example_1:1.248 secs

example_2:1.924 secs

example_3:5.769 secs

300w 第四次

example_1:0.782 secs

example_2:1.582 secs

example_3:5.324 secs

limit 34105450, 10

example_1:17.915 secs

example_2:51.673 secs

example_3:209.536 secs

写于2018年03月04日,由 archive.org 找回