今天写了个sql,为了验证下不同sql写法性能上有何区别,我专门用了两种实现方式,结果发现差别还蛮大的。
需求:查询出口额在前十大的企业信息。
实现方式一:
SELECT A.V_COCODE , A.COMPANY , A.TOTALDOLLAR FROM (SELECT T1.V_COCODE, T1.COMPANY, SUM(T.EXPORTSUM) TOTALDOLLAR, ROW_NUMBER() OVER(ORDER BY SUM(T.EXPORTSUM) DESC) ROWNO FROM F_CUSTOM_EXPORTDETAIL T, D_CUSTOM_COMPANY T1 WHERE T.COCODE = T1.COCODE AND T.MONTHID BETWEEN 201201 AND 201301 AND T.YEARID BETWEEN 2012 AND 2013 GROUP BY T1.V_COCODE, T1.COMPANY) A WHERE A.ROWNO <= 10
实现方式二:
SELECT B.V_COCODE 海关企业编码, B.COMPANY 海关企业名称, A.TOTALDOLLAR 出口额 FROM (SELECT T.COCODE, SUM(T.EXPORTSUM) TOTALDOLLAR, ROW_NUMBER() OVER(ORDER BY SUM(T.EXPORTSUM) DESC) ROWNO FROM F_CUSTOM_EXPORTDETAIL T WHERE T.MONTHID BETWEEN 201201 AND 201301 AND T.YEARID BETWEEN 2012 AND 2013 GROUP BY T.COCODE) A, D_CUSTOM_COMPANY B WHERE A.COCODE = B.COCODE AND A.ROWNO <= 10
在我的工作机上,方式一执行时间为2‘29,方式二执行时间为0’56,很明显方式二效率更高。
这是为什么呢?先用执行计划验证上面的结论:
方式一执行计划:
方式二执行计划:
可以看出,方式一比方式二开销更大。
看执行计划也可以看出,遍历这两个表所花的时间一样,主要区别就在于group by,方式一的两个表先进行关联,然后在group by,开销明显更大。
因此,group by的时候,关联的表越少越好。(这里有个前提:访问detail表中的结果集较大时,我们应该这么做。但如果增加一个过滤条件,使结果集较少,那么多表进行关联,性能未必差,因为基于成本的优化器会帮我们选择最佳的执行路径。)
另外,因为F_CUSTOM_EXPORTDETAIL是按年分区的分区表,所以在查询某个月份的数据时,必须要指出相应的年份,否则数据库在查询时,不会根据分区进行查找,这样速度会相当慢。
上面的例子只是对企业这个维度进行了汇总,而且企业是有维表的,所以这么处理可以提高性能。如果要按企业、省份来汇总,如此处理就会有问题。因为detail表中没有省份信息,必须通过地区找到对应的省份,所以无法先按省份汇总,然后再到省份维表中查找对应省份。如果要按上面的处理方式,就需要两层group by,这样性能反倒会降低很多。
因此,基本上可以得到一个结论:如果只用一次group by能搞定的,就只用一次group by,并且group by过程中关联的表越少越好。当然,具体情况还需要具体分析。