SQL性能 - 9dian/Index GitHub Wiki
示例表结构
CREATE TABLE finance.citic_dayend ( id integer NOT NULL DEFAULT nextval('finance.t_citic_dayend_id_seq'::regclass), date_key integer, thoroughfare_id integer, success_count bigint, success_amount numeric(20,6), refund_count bigint, refund_amount numeric(20,6), bill_rate numeric(10,4), mch_fee numeric(20,2), cost_rate numeric(10,4), third_fee numeric(20,2), channel_exe_rate numeric(15,4), total_benefit_fee numeric(20,6), actual_benefit_fee numeric(20,2), a_actual_benefit_fee numeric(20,2), channel_id character varying(32), channel_name character varying(64), merchant_id character varying(16), merchant_name character varying(128), pay_name character varying(64), accept_org_id character varying(32), pay_mode character varying(32), thoroughfare_name character varying(128), channel_path character varying(2048), account_name character varying(128), benefit_channel character varying(32), -- 受益渠道 accept_org_name character varying(64), -- 受理机构名称 one_to_three character varying(8), -- 一分三属性 rate_id numeric(11,0), -- 费率主键 channel_path_back character varying(2048) -- 渠道链路channel_path的反排序链路 ) WITH ( OIDS=FALSE ) DISTRIBUTED BY (id) PARTITION BY RANGE(date_key) ( PARTITION before2017 START (20100101) END (20170101) WITH (appendonly=true, orientation=column, compresstype=zlib, compresslevel=5) COLUMN id ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN date_key ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN thoroughfare_id ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN success_count ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN success_amount ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN refund_count ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN refund_amount ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN bill_rate ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN mch_fee ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN cost_rate ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN third_fee ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN channel_exe_rate ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN total_benefit_fee ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN actual_benefit_fee ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN a_actual_benefit_fee ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN channel_id ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN channel_name ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN merchant_id ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN merchant_name ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN pay_name ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN accept_org_id ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN pay_mode ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN thoroughfare_name ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN channel_path ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN account_name ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN benefit_channel ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN accept_org_name ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN one_to_three ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN rate_id ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768) COLUMN channel_path_back ENCODING (compresstype=zlib, compresslevel=5, blocksize=32768), PARTITION year2017 START (20170101) END (20180101), PARTITION year2018 START (20180101) END (20190101), PARTITION year2019 START (20190101) END (20200101) ) ; ALTER TABLE finance.citic_dayend OWNER TO bi; GRANT ALL ON TABLE finance.citic_dayend TO bi; GRANT SELECT ON TABLE finance.citic_dayend TO bi_ro; COMMENT ON COLUMN finance.citic_dayend.benefit_channel IS '受益渠道'; COMMENT ON COLUMN finance.citic_dayend.accept_org_name IS '受理机构名称'; COMMENT ON COLUMN finance.citic_dayend.one_to_three IS '一分三属性'; COMMENT ON COLUMN finance.citic_dayend.rate_id IS '费率主键'; COMMENT ON COLUMN finance.citic_dayend.channel_path_back IS '渠道链路channel_path的反排序链路';
SQL1: join时不包含date_key
SELECT cd.date_key,cd.account_name,cd.accept_org_id,cd.accept_org_name,cd.thoroughfare_id,cd.thoroughfare_name,cd.pay_mode,cd.pay_name,cd.channel_id, cd.channel_name,cd.merchant_id,cd.merchant_name,cd.success_count,cd.success_amount,cd.refund_count,cd.refund_amount,cd.bill_rate,cd.mch_fee, cd.cost_rate,cd.third_fee,t.wft_benefit_rate,t.wft_benefit,t.wft_tec_rate,t.wft_tec_fee, 0 wft_tail,cd.rate_id FROM ( select n.date_key,n.thoroughfare_id,n.success_count,n.success_amount,n.refund_count,n.refund_amount,n.bill_rate,n.mch_fee,n.cost_rate,n.third_fee,n.channel_id,n.channel_name,n.merchant_id,n.merchant_name,n.pay_name,n.accept_org_id,n.pay_mode,n.thoroughfare_name,n.account_name,n.accept_org_name,n.rate_id from ( SELECT row_number() over (PARTITION by c.merchant_id, c.pay_mode, c.rate_id, c.thoroughfare_id) rn, c.date_key,c.thoroughfare_id,c.success_count,c.success_amount,c.refund_count,c.refund_amount,c.bill_rate,c.mch_fee,c.cost_rate,c.third_fee,c.channel_id,c.channel_name,c.merchant_id,c.merchant_name,c.pay_name,c.accept_org_id,c.pay_mode,c.thoroughfare_name,c.account_name,c.accept_org_name,c.rate_id FROM finance.citic_dayend c where c.one_to_three='0' AND c.date_key >= 20180601 AND c.date_key<=20180630 AND c.accept_org_id = '755010000003' ) n WHERE n.rn = 1 )cd JOIN ( SELECT d.date_key,d.account_name,d.accept_org_id,d.channel_id,d.merchant_id,d.thoroughfare_id,d.pay_mode,d.rate_id, SUM(CASE WHEN (d.benefit_channel='ALL_CITI0C_HEAD_784191' OR d.benefit_channel='102173128950') THEN d.channel_exe_rate ELSE 0 END ) wft_benefit_rate, SUM(CASE WHEN (d.benefit_channel='ALL_CITI0C_HEAD_784191' OR d.benefit_channel='102173128950') THEN d.actual_benefit_fee ELSE 0 END ) wft_benefit, SUM(CASE WHEN (d.benefit_channel!='ALL_CITI0C_HEAD_784191' AND d.benefit_channel!='102173128950') THEN d.channel_exe_rate ELSE 0 END ) wft_tec_rate, SUM(CASE WHEN (d.benefit_channel!='ALL_CITI0C_HEAD_784191' AND d.benefit_channel!='102173128950') THEN d.actual_benefit_fee ELSE 0 END ) wft_tec_fee FROM finance.citic_dayend d WHERE d.one_to_three='0' AND d.date_key >= 20180601 AND d.date_key<=20180630 AND d.accept_org_id = '755010000003' GROUP BY d.date_key,d.account_name,d.accept_org_id,d.channel_id,d.merchant_id,d.thoroughfare_id,d.pay_mode,d.rate_id ) t ON cd.merchant_id=t.merchant_id AND cd.thoroughfare_id=t.thoroughfare_id AND cd.pay_mode=t.pay_mode AND cd.rate_id=t.rate_id
SQL2: join时包含date_key
SELECT cd.date_key,cd.account_name,cd.accept_org_id,cd.accept_org_name,cd.thoroughfare_id,cd.thoroughfare_name,cd.pay_mode,cd.pay_name,cd.channel_id, cd.channel_name,cd.merchant_id,cd.merchant_name,cd.success_count,cd.success_amount,cd.refund_count,cd.refund_amount,cd.bill_rate,cd.mch_fee, cd.cost_rate,cd.third_fee,t.wft_benefit_rate,t.wft_benefit,t.wft_tec_rate,t.wft_tec_fee, 0 wft_tail,cd.rate_id FROM ( select n.date_key,n.thoroughfare_id,n.success_count,n.success_amount,n.refund_count,n.refund_amount,n.bill_rate,n.mch_fee,n.cost_rate,n.third_fee,n.channel_id,n.channel_name,n.merchant_id,n.merchant_name,n.pay_name,n.accept_org_id,n.pay_mode,n.thoroughfare_name,n.account_name,n.accept_org_name,n.rate_id from ( SELECT row_number() over (PARTITION by c.merchant_id, c.pay_mode, c.rate_id, c.thoroughfare_id) rn, c.date_key,c.thoroughfare_id,c.success_count,c.success_amount,c.refund_count,c.refund_amount,c.bill_rate,c.mch_fee,c.cost_rate,c.third_fee,c.channel_id,c.channel_name,c.merchant_id,c.merchant_name,c.pay_name,c.accept_org_id,c.pay_mode,c.thoroughfare_name,c.account_name,c.accept_org_name,c.rate_id FROM finance.citic_dayend c where c.one_to_three='0' AND c.date_key >= 20180601 AND c.date_key<=20180630 AND c.accept_org_id = '755010000003' ) n WHERE n.rn = 1 )cd JOIN ( SELECT d.date_key,d.account_name,d.accept_org_id,d.channel_id,d.merchant_id,d.thoroughfare_id,d.pay_mode,d.rate_id, SUM(CASE WHEN (d.benefit_channel='ALL_CITI0C_HEAD_784191' OR d.benefit_channel='102173128950') THEN d.channel_exe_rate ELSE 0 END ) wft_benefit_rate, SUM(CASE WHEN (d.benefit_channel='ALL_CITI0C_HEAD_784191' OR d.benefit_channel='102173128950') THEN d.actual_benefit_fee ELSE 0 END ) wft_benefit, SUM(CASE WHEN (d.benefit_channel!='ALL_CITI0C_HEAD_784191' AND d.benefit_channel!='102173128950') THEN d.channel_exe_rate ELSE 0 END ) wft_tec_rate, SUM(CASE WHEN (d.benefit_channel!='ALL_CITI0C_HEAD_784191' AND d.benefit_channel!='102173128950') THEN d.actual_benefit_fee ELSE 0 END ) wft_tec_fee FROM finance.citic_dayend d WHERE d.one_to_three='0' AND d.date_key >= 20180601 AND d.date_key<=20180630 AND d.accept_org_id = '755010000003' GROUP BY d.date_key,d.account_name,d.accept_org_id,d.channel_id,d.merchant_id,d.thoroughfare_id,d.pay_mode,d.rate_id ) t ON cd.merchant_id=t.merchant_id AND cd.thoroughfare_id=t.thoroughfare_id AND cd.pay_mode=t.pay_mode AND cd.rate_id=t.rate_id AND cd.date_key=t.date_key
使用窗口函数,避免Join两个子查询。
SELECT d.date_key,d.account_name,d.accept_org_id,d.rate_id, accept_org_name,thoroughfare_id,thoroughfare_name,pay_mode,pay_name,channel_id, channel_name,merchant_id,merchant_name,success_count,success_amount,refund_count,refund_amount,bill_rate,mch_fee, cost_rate,third_fee, 0 wft_tail, SUM(CASE WHEN (d.benefit_channel='ALL_CITI0C_HEAD_784191' OR d.benefit_channel='102173128950') THEN d.channel_exe_rate ELSE 0 END ) OVER (PARTITION BY d.date_key,d.account_name,d.accept_org_id,d.channel_id,d.merchant_id,d.thoroughfare_id,d.pay_mode,d.rate_id) wft_benefit_rate, SUM(CASE WHEN (d.benefit_channel='ALL_CITI0C_HEAD_784191' OR d.benefit_channel='102173128950') THEN d.actual_benefit_fee ELSE 0 END ) OVER (PARTITION BY d.date_key,d.account_name,d.accept_org_id,d.channel_id,d.merchant_id,d.thoroughfare_id,d.pay_mode,d.rate_id) wft_benefit, SUM(CASE WHEN (d.benefit_channel!='ALL_CITI0C_HEAD_784191' AND d.benefit_channel!='102173128950') THEN d.channel_exe_rate ELSE 0 END ) OVER (PARTITION BY d.date_key,d.account_name,d.accept_org_id,d.channel_id,d.merchant_id,d.thoroughfare_id,d.pay_mode,d.rate_id) wft_tec_rate, SUM(CASE WHEN (d.benefit_channel!='ALL_CITI0C_HEAD_784191' AND d.benefit_channel!='102173128950') THEN d.actual_benefit_fee ELSE 0 END ) OVER (PARTITION BY d.date_key,d.account_name,d.accept_org_id,d.channel_id,d.merchant_id,d.thoroughfare_id,d.pay_mode,d.rate_id) wft_tec_fee FROM finance.citic_dayend d WHERE d.one_to_three='0' AND d.date_key >= 20180601 AND d.date_key<=20180630 AND d.accept_org_id = '755010000003'