PawSQL优化 | 分页查询太慢?别忘了投影下推!

2024-08-20 20:15:23 浏览数 (3)

在进行数据库应用开发中,分页查询是一项非常常见而又至关重要的任务。但你是否曾因为需要获取总记录数的性能而感到头疼?现在,让PawSQL的投影下推优化来帮你轻松解决这一问题!本文以TPCH的Q12为案例进行验证,经过PawSQL的优化后性能提升6000多倍!

分页查询的痛点

在进行分页查询时,我们通常需要获取总记录数以计算总页数。绝大多少程序员会在原查询上添加count(1)count(*),性能可能会非常差,特别是在面对复杂查询时。其实对于这个场景,有很大的概率能够对SQL进行重写优化。

解决方案

PawSQL的投影下推优化功能,能够智能地识别并保留关键列,生成一个等价但更高效的count查询。以下是具体的优化步骤:

获取原始分页查询:首先识别原始查询结构,例如:

代码语言:javascript复制
SELECT * FROM (
 SELECT col1, col2, ..., colN
 FROM table
 WHERE ...
) dt
ORDER BY ...
LIMIT ?, ?

人工改写成记录数查询

  • 将外层的SELECT *更改为SELECT count(1)...
  • 删除最外层的 ORDER BY子句和LIMIT子句
代码语言:javascript复制
SELECT count(1) FROM ( SELECT col1, col2, ..., colN FROM t1, t2 WHERE ...) dt

PawSQL投影下推优化:PawSQL可以对对内层查询进行投影下推优化,仅保留对结果有影响的列,同时可能触发其他的重写优化,譬如表关联消除,推荐覆盖索引等。

生成高效查询:经过PawSQL的优化,新查询可能如下:

代码语言:javascript复制
SELECT count(1)
FROM (
 SELECT 1
 FROM t1
 WHERE ...
)

TPCH案例解析

原Q12:货运模式和订单优先级查询
代码语言:javascript复制
SELECT
L_SHIPMODE,
SUM(CASE
WHEN O_ORDERPRIORITY = '1-URGENT'
OR O_ORDERPRIORITY = '2-HIGH'
THEN 1
ELSE 0
END) AS HIGH_LINE_COUNT,
SUM(CASE
WHEN O_ORDERPRIORITY <> '1-URGENT'
AND O_ORDERPRIORITY <> '2-HIGH'
THEN 1
ELSE 0
END) AS LOW_LINE_COUNT
FROM
ORDERS,
LINEITEM
WHERE
O_ORDERKEY = L_ORDERKEY
AND L_SHIPMODE IN ('RAIL', 'FOB')
AND L_COMMITDATE < L_RECEIPTDATE
AND L_SHIPDATE < L_COMMITDATE
AND L_RECEIPTDATE >= DATE '2021-01-01'
AND L_RECEIPTDATE < DATE '2021-01-01'   INTERVAL '1' YEAR
GROUP BY
L_SHIPMODE
ORDER BY
L_SHIPMODE;

查询总记录数的SQL

代码语言:javascript复制
select count(*)
from (
    SELECT
    L_SHIPMODE,
    SUM(CASE
    WHEN O_ORDERPRIORITY = '1-URGENT'
    OR O_ORDERPRIORITY = '2-HIGH'
    THEN 1
    ELSE 0
    END) AS HIGH_LINE_COUNT,
    SUM(CASE
    WHEN O_ORDERPRIORITY <> '1-URGENT'
    AND O_ORDERPRIORITY <> '2-HIGH'
    THEN 1
    ELSE 0
    END) AS LOW_LINE_COUNT
    FROM
    ORDERS,
    LINEITEM
    WHERE
    O_ORDERKEY = L_ORDERKEY
    AND L_SHIPMODE IN ('RAIL', 'FOB')
    AND L_COMMITDATE < L_RECEIPTDATE
    AND L_SHIPDATE < L_COMMITDATE
    AND L_RECEIPTDATE >= DATE '2021-01-01'
    AND L_RECEIPTDATE < DATE '2021-01-01'   INTERVAL '1' YEAR
    GROUP BY
    L_SHIPMODE
  ) as t

PawSQL优化过程

  1. PawSQL首先进行投影下推优化,可以看到派生表的列被消除
代码语言:javascript复制
select count(*)
from ( 
   select 1
   from ORDERS, LINEITEM
   where ORDERS.O_ORDERKEY = LINEITEM.L_ORDERKEY
   and LINEITEM.L_SHIPMODE in ('RAIL', 'FOB')
   and LINEITEM.L_COMMITDATE < LINEITEM.L_RECEIPTDATE
   and LINEITEM.L_SHIPDATE < LINEITEM.L_COMMITDATE
   and LINEITEM.L_RECEIPTDATE >= date '2021-01-01'
   and LINEITEM.L_RECEIPTDATE < date '2021-01-01'   interval '1' YEAR
   group by LINEITEM.L_SHIPMODE
   ) as t

2. 选择列被消除,从而触发了表连接消除(ORDERS被消除)

代码语言:javascript复制
select /*QB_1*/ count(*)
from (
 select /*QB_2*/ 1
 from LINEITEM
 where LINEITEM.L_SHIPMODE in ('RAIL', 'FOB')
 and LINEITEM.L_COMMITDATE < LINEITEM.L_RECEIPTDATE
 and LINEITEM.L_SHIPDATE < LINEITEM.L_COMMITDATE
 and LINEITEM.L_RECEIPTDATE >= date '2021-01-01'
 and LINEITEM.L_RECEIPTDATE < date '2021-01-01'   interval '1' YEAR
 group by LINEITEM.L_SHIPMODE
 ) as t

3. PawSQL接着推荐最优索引(索引查找 避免排序 避免回表)

代码语言:javascript复制
CREATE INDEX PAWSQL_IDX0245689906 ON tpch_pkfk.lineitem(L_SHIPMODE,L_RECEIPTDATE,L_COMMITDATE,L_SHIPDATE);

4. 性能验证性能提升

执行时间从优化前的453.48ms,降低到0.065ms,性能提升6975倍!

其他应用场景

除了分页查询,PawSQL的投影下推优化还能在以下场景中大放异彩:

  • 星号查询优化:避免使用SELECT *带来的数据传输和计算开销。
  • EAV模型数据优化:减少高度规范化数据模型的连接操作成本。
  • 视图和嵌套视图优化:简化复杂视图查询,降低计算开销。
  • 报表查询优化:提高报表生成的性能,尤其是在处理多维度数据时。

总结

PawSQL的投影下推优化技术,是一种在任何需要处理多余列的查询场景中都能提升查询性能的有效手段。通过减少数据传输和降低计算复杂度,PawSQL让数据库查询变得更加高效。

0 人点赞