首页 > 解决方案 > 不同的SQL写法造成不同的时间成本

问题描述

我正在尝试select every n-th row from mysql,我阅读了这个答案

有一张桌子sys_request_log

CREATE TABLE `sys_request_log` 
(
    `id` bigint(20) NOT NULL,
    `user_id` bigint(20) DEFAULT NULL,
    `ip` varchar(50) DEFAULT NULL,
    `data` mediumtext,
    `create_time` datetime DEFAULT NULL,
    PRIMARY KEY (`id`) USING BTREE,
    KEY `user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

它包含 11837 行。

我尝试select every 5-th row from table,首先我尝试执行:

SELECT
    * 
FROM
    (SELECT @ROW := @ROW + 1 AS rownum, log.* FROM ( SELECT @ROW := 0 ) r, sys_request_log log ) ranked 
WHERE
    rownum % 5 = 1 

结果是:

rownum  id                  user_id             create_time
-------------------------------------------------------------------
 1      1271446699071639552 1                   2020-06-12 22:18:10
 6      1271446948980854784 1                   2020-06-12 22:19:10
11      1271447016878247936 1269884071484461056 2020-06-12 22:19:26

耗时1.001秒

我发现有一个不相关的专栏rownum。所以我像这样修改SQL:

SELECT
    log.*
FROM
    (SELECT @ROW := @ROW + 1 AS rownum FROM (SELECT @ROW := 0) t) r,
    sys_request_log log
WHERE
    rownum % 5 = 1

现在结果是干净的(没有 rownum),但它花费了 2.516 秒的时间!

为什么?

mysql版本:5.7.26-log

标签: mysqlsql

解决方案


在第一种情况下,行号值是在从 table() 中选择的过程中选择的,但是对于第二种情况,由于每个单独的 rownum 与每个单独的行的出现,子查询和从表中的选择之间sys_request_log会出现笛卡尔积表的值。rCROSS JOIN


推荐阅读