从 TPCH 测试学习性能优化技巧之 Q12

一、     查询要求

Q12 语句查询某一年在指定的两种货运模式下,早于交货日期发货而消费者迟于交货日期收到货物的订单中,按货运模式分组统计订单优先级为 URGENT 或 HIGH 的订单数量,以及不是这 2 种优先级的订单的数量。

Q12语句的特点是:带有分组、排序、聚集操作并存的两表连接查询操作。

 

二、     Oracle执行

Oracle编写的查询SQL语句如下:

select  /*+ parallel(n) */

         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 ('TRUCK', 'MAIL')

         and l_commitdate < l_receiptdate

         and l_shipdate < l_commitdate

         and l_receiptdate >= date '1995-01-01'

         and l_receiptdate < date '1995-01-01' + interval '1' year

group by

         l_shipmode

order by

         l_shipmode;

其中/*+ parallel(n) */ Oracle的并行查询语法,n是并行数。

脚本执行时间,单位:秒

并行数

1

2

4

8

12

Oracle

441

341

264

180

184

三、     SPL优化

这里的orderslineitem主子表关联优化原理与Q3中类似。

注意到SQLhigh_line_countlow_line_count的条件正好相反,其中一个可以被另一个用更简单的计算式计算出来。而且这两个计算列只和orders表相关,可先将其计算出来后再与lineitem做连接,这样比先连接再计算的计算量要少很多,因为orders表要比lineitem表小很多。

 

SPL脚本如下:


A

1

=now()

2

1995-1-1

3

=elapse@y(A2, 1)

4

=["MAIL",   "TRUCK"]

5

=file("orders.ctx").open().cursor@m(O_ORDERKEY,O_ORDERPRIORITY).run(O_ORDERPRIORITY=if(O_ORDERPRIORITY=="1-URGENT"   || O_ORDERPRIORITY=="2-HIGH",1,0))

6

=file("lineitem.ctx").open().news(A5,L_SHIPMODE,L_RECEIPTDATE,L_SHIPDATE,L_COMMITDATE,O_ORDERPRIORITY;L_RECEIPTDATE>=A2   && L_RECEIPTDATE<A3 && A4.contain(L_SHIPMODE)).select(  L_COMMITDATE<L_RECEIPTDATE && L_SHIPDATE<L_COMMITDATE)

7

=A6.groups(L_SHIPMODE;sum(O_ORDERPRIORITY):high_line_count,   sum(1-O_ORDERPRIORITY):low_line_count)

8

return interval@ms(A1,now())

 

脚本执行时间,单位:秒

并行数

1

2

4

8

12

Oracle

441

341

264

180

184

SPL组表

200

100

50

28

20