2016-11-18 13 views
3

Я пытаюсь запросить базу данных другого программного обеспечения, поэтому я не могу контролировать индексы, функции и т. Д. У меня есть доступ только для чтения, поэтому я не верю, что могу сделать временную таблицу даже. Я просто не понимаю, почему разница.Postgresql 9.2 - Почему разница в скорости - SQL Subselect и JOIN?

Вот мой основной вопрос:

WITH vCriteria AS (
    SELECT vSub.visit_id, vd.vdiag_diag from visit vSUB 
    JOIN insurance_company_table1 inscomp1 ON inscomp1.inscomp1_comp = vSub.visit_ins 
     and inscomp1.inscomp1_arid = vSub.visit_arid 
    JOIN da152 da ON da.da152_arid = vSub.visit_arid 
    LEFT JOIN insurance1 i ON i.is1_num = vSub.visit_id AND i.is1_ins_full = vSub.visit_ins 
    LEFT JOIN visit_diagnosis vd ON vd.vdiag_visit_key = vSub.visit_id 

    WHERE vSub.visit_mr_fdt 
    BETWEEN (now() - 50 * INTERVAL '1 day') AND (now() + 10 * INTERVAL '1 day') 
    AND NULLIF (vSub.visit_disch_date, '0001-01-01' ::date) IS NOT NULL 
    AND Now() >=(vSub.visit_disch_date + inscomp1.inscomp1_lagdays * INTERVAL '1 day') 
    AND vSub.visit_servicecd_key ~ '^[0-9]+$|[FHJbKkN\\+]' = false 
    AND LEFT (vSub.visit_id, 1) NOT IN ('F', 'P', 'J') 
    AND NULLIF (i.is1_bill_dt, '0001-01-01' ::date) IS NULL 
    AND vSub.visit_disch_date <= da.da152_chgdt 
) 

Select vCriteria.* from vCriteria 

Он выполняет в 609 мс

добавить 1 присоединиться, и это занимает гораздо больше времени: LEFT JOIN visit_diagnosis VD ON vd.vdiag_visit_key = vSub. visit_id

WITH vCriteria AS (
    SELECT vSub.visit_id, vd.vdiag_diag from visit vSUB 
    JOIN insurance_company_table1 inscomp1 ON inscomp1.inscomp1_comp = vSub.visit_ins 
     and inscomp1.inscomp1_arid = vSub.visit_arid 
    JOIN da152 da ON da.da152_arid = vSub.visit_arid 
    LEFT JOIN insurance1 i ON i.is1_num = vSub.visit_id AND i.is1_ins_full = vSub.visit_ins 
    LEFT JOIN visit_diagnosis vd ON vd.vdiag_visit_key = vSub.visit_id 

    WHERE vSub.visit_mr_fdt 
    BETWEEN (now() - 50 * INTERVAL '1 day') AND (now() + 10 * INTERVAL '1 day') 
    AND NULLIF (vSub.visit_disch_date, '0001-01-01' ::date) IS NOT NULL 
    AND Now() >=(vSub.visit_disch_date + inscomp1.inscomp1_lagdays * INTERVAL '1 day') 
    AND vSub.visit_servicecd_key ~ '^[0-9]+$|[FHJbKkN\\+]' = false 
    AND LEFT (vSub.visit_id, 1) NOT IN ('F', 'P', 'J') 
    AND NULLIF (i.is1_bill_dt, '0001-01-01' ::date) IS NULL 
    AND vSub.visit_disch_date <= da.da152_chgdt 
) 

Select vCriteria.* from vCriteria 

Он занимает более 13 секунд, чтобы выполнить

Таким образом, приведенный выше запрос очень упрощен, вот примеры, которые я попробовал. Если я что-то вроде этого:

SELECT t.id_field from table t 
JOIN . . . 
JOIN . . .  
WHERE <10 rows of filtering criteria> 

он выполняет в 766 мс и возвращает 411 записей

Когда я бегу в одиночку этот вопрос:

select t.id_field, t2.field1 from table t 
LEFT JOIN table2 t2 ON t2.t_id_field = t.id_field 
WHERE t.id_field in (<I list out the varchar(8) values here from first query>) 

Он выполняет в 3.031 сек

Но если я попытаюсь поставить запросы вместе, как это

select t.id_field, t2.field1 from table t 
LEFT JOIN table2 t2 ON t2.t_id_field = t.id_field 
WHERE t.id_field in ( 
    SELECT t.id_field from table t 
    JOIN . . . 
    JOIN . . .  
    WHERE <10 rows of filtering criteria> 
) 

Это занимает 19,406 сек

Я попробовал с утверждением вроде так:

WITH vt AS (
    SELECT t.id_field from table t 
    JOIN . . . 
    JOIN . . .  
    WHERE <10 rows of filtering criteria> 
) 
select vt.id_field, t2.field1 from vt 
LEFT JOIN table2 t2 ON t2.t_id_field = vt.id_field 

Он выполняет за 12 секунд

Я попытался это:

select t.id_field, t2.field1 from ( 
     SELECT tsub.id_field from table tsub 
     JOIN . . . 
     JOIN . . .  
     WHERE <10 rows of filtering criteria> 
    ) t 
LEFT JOIN table2 t2 ON t2.t_id_field = t.id_field 

Выполняет в 12.750 сек.

Другая попытка была только это:

SELECT t.id_field, t2.field1 from table t 
JOIN . . . 
JOIN . . . 
LEFT JOIN table2 t2 ON t2.t_id_field = t.id_field 
WHERE <10 rows of filtering criteria> 

Выполненный в 12.813 сек

Любые мысли о том, как получить его, по крайней мере, 3 секунды, как один выше, где я просто положить значения вручную?

Это план выполнения

QUERY PLAN 
Nested Loop Left Join (cost=109243.37..119017.89 rows=1 width=83) 
    CTE vc 
    -> Nested Loop (cost=14871.86..109243.37 rows=1 width=7) 
      -> Nested Loop (cost=14871.86..109242.01 rows=4 width=24) 
       Join Filter: ((vsub.visit_disch_date <= da.da152_chgdt) AND (vsub.visit_arid = da.da152_arid)) 
       -> Index Scan using da152_pkey on da152 da (cost=0.00..10.40 rows=4 width=9) 
       -> Materialize (cost=14871.86..109230.80 rows=12 width=19) 
         -> Hash Right Join (cost=14871.86..109230.74 rows=12 width=19) 
          Hash Cond: (((i.is1_num)::text = (vsub.visit_id)::text) AND ((i.is1_ins_full)::text = (vsub.visit_ins)::text)) 
          Filter: (NULLIF(i.is1_bill_dt, '0001-01-01'::date) IS NULL) 
          -> Seq Scan on insurance1 i (cost=0.00..90993.64 rows=336264 width=14) 
          -> Hash (cost=14837.16..14837.16 rows=2313 width=19) 
            -> Seq Scan on visit vsub (cost=0.00..14837.16 rows=2313 width=19) 
             Filter: ((NULLIF(visit_disch_date, '0001-01-01'::date) IS NOT NULL) AND ((visit_servicecd_key)::text !~ '^[0-9]+$|[FHJbKkN\\+]'::text) AND ("left"((visit_id)::text, 1) <> ALL ('{F,P,J}'::text[])) AND (visit_mr_fdt >= (now() - '50 days'::interval)) AND (visit_mr_fdt <= (now() + '10 days'::interval))) 
      -> Index Scan using inscomp1_pkey on insurance_company_table1 inscomp1 (cost=0.00..0.33 rows=1 width=11) 
       Index Cond: ((inscomp1_arid = vsub.visit_arid) AND ((inscomp1_comp)::text = (vsub.visit_ins)::text)) 
       Filter: (now() >= (vsub.visit_disch_date + ((inscomp1_lagdays)::double precision * '1 day'::interval))) 
    -> CTE Scan on vc (cost=0.00..0.02 rows=1 width=12) 
    -> Index Scan using vdiag_pkey on visit_diagnosis vd (cost=0.00..9774.48 rows=1 width=71) 
     Index Cond: ((vdiag_visit_key)::text = (vc.visit_id)::text) 
     Filter: ((vdiag_type)::text = 'A'::text) 

И Объяснение (Анализировать, многословный) (ДЛЯ "С" QUERY примере выше)

QUERY PLAN 
Nested Loop Left Join (cost=109243.36..119017.87 rows=1 width=83) (actual time=418.062..13796.260 rows=414 loops=1) 
    Output: vc.visit_id, vd.vdiag_visit_key, vd.vdiag_arxseq, vd.vdiag_element, vd.vdiag_type, vd.vdiag_date, vd.vdiag_diag, vd.vdiag_arid 
    CTE vc 
    -> Nested Loop (cost=14871.84..109243.36 rows=1 width=7) (actual time=404.477..1006.518 rows=414 loops=1) 
      Output: vsub.visit_id 
      -> Nested Loop (cost=14871.84..109242.00 rows=4 width=24) (actual time=404.432..990.137 rows=418 loops=1) 
       Output: vsub.visit_id, vsub.visit_ins, vsub.visit_arid, vsub.visit_disch_date, da.da152_arid 
       Join Filter: ((vsub.visit_disch_date <= da.da152_chgdt) AND (vsub.visit_arid = da.da152_arid)) 
       Rows Removed by Join Filter: 1374 
       -> Index Scan using da152_pkey on public.da152 da (cost=0.00..10.40 rows=4 width=9) (actual time=0.004..0.017 rows=4 loops=1) 
         Output: da.da152_rel_file_key_num, da.da152_contrl, da.da152_rcdt, da.da152_chgdt, da.da152_ar_rev, da.da152_ar_rc, da.da152_ar_rcar, da.da152_unpost, da.da152_lrun, da.da152_ar_month, da.da152_insdt, da.da152_otc_rcdt, da.da152_sum_rev, da.da152_sum_rc, da.da152_sum_rcar, da.da152_begbal, da.da152_netar, da.da152_arend, da.da152_eomtrial, da.da152_rc_da, da.da152_rc_amt_otc, da.da152_rc_amt_cp, da.da152_chg_thru, da.da152_ar_ldom, da.da152_csnum, da.da152_sec_e_bill, da.da152_uform, da.da152_jform, da.da152_rate, da.da152_contract_bill, da.da152_up_front, da.da152_bad_debt, da.da152_pat_refund, da.da152_2cnd_ins, da.da152_pat_type1, da.da152_pat_type2, da.da152_pat_srvcd1_old, da.da152_pat_srvcd2_old, da.da152_wo_colcd1, da.da152_wo_alpha1s, da.da152_wo_alpha1e, da.da152_wo_colcd2, da.da152_wo_alpha2s, da.da152_wo_alpha2e, da.da152_wo_colcd3, da.da152_wo_alpha3s, da.da152_wo_alpha3e, da.da152_ins_prim, da.da152_tic_xfc1, da.da152_tic_xfc2, da.da152_ins_fc, da.da152_wo_sitnum, da.da152_wo_sit_cd, da.da152_ins2dt, da.da152_multicoqual, da.da152_multicoid, da.da152_multicodir, da.da152_multicoglnum, da.da152_pat_srvcd1, da.da152_pat_srvcd2, da.da152_adchg, da.da152_adchg_var, da.da152_month_closedt, da.da152_pat_colcd, da.da152_nonaracct, da.da152_isfup_days, da.da152_arid 
       -> Materialize (cost=14871.84..109230.79 rows=12 width=19) (actual time=101.103..246.563 rows=448 loops=4) 
         Output: vsub.visit_id, vsub.visit_ins, vsub.visit_arid, vsub.visit_disch_date 
         -> Hash Right Join (cost=14871.84..109230.73 rows=12 width=19) (actual time=404.408..983.328 rows=448 loops=1) 
          Output: vsub.visit_id, vsub.visit_ins, vsub.visit_arid, vsub.visit_disch_date 
          Hash Cond: (((i.is1_num)::text = (vsub.visit_id)::text) AND ((i.is1_ins_full)::text = (vsub.visit_ins)::text)) 
          Filter: (NULLIF(i.is1_bill_dt, '0001-01-01'::date) IS NULL) 
          Rows Removed by Filter: 2018 
          -> Seq Scan on public.insurance1 i (cost=0.00..90993.64 rows=336264 width=14) (actual time=0.002..284.366 rows=341073 loops=1) 
            Output: i.is1_num, i.is1_ins_full, i.is1_set, i.is1_prim, i.is1_stay, i.is1_direct, i.is1_admit, i.is1_disc, i.is1_from, i.is1_to, i.is1_app_sent, i.is1_app_rec, i.is1_gen_dt, i.is1_ck_dt, i.is1_contract_old, i.is1_bill_dt, i.is1_pd_dt1, i.is1_pd_amt1, i.is1_pd_dt2, i.is1_pd_amt2, i.is1_pd_dt3, i.is1_pd_amt3, i.is1_pd_status, i.is1_med_ness, i.is1_bl_furn, i.is1_bl_rep, i.is1_bl_n_rep, i.is1_bl_rate, i.is1_bl_chg, i.is1_bl_non, i.is1_coamt, i.is1_expay, i.is1_semi_rate, i.is1_diem, i.is1_cd, i.is1_typrm, i.is1_qty, i.is1_chg, i.is1_non, i.is1_opcd, i.is1_opdate, i.is1_opdesc, i.is1_opchg, i.is1_opphy, i.is1_totchg, i.is1_totnon, i.is1_maxlines, i.is1_totlines, i.is1_apc_sw, i.is1_eapc_reim, i.is1_eapc_copay, i.is1_eapc_contr, i.is1_eapc_ded, i.is1_eapc_outlr, i.is1_aapc_reim, i.is1_aapc_copay, i.is1_aapc_contr, i.is1_aapc_ded, i.is1_aapc_outlr, i.is1_mr_okayed, i.is1_mr_ok_init, i.is1_a_ded, i.is1_dayfull, i.is1_dayco, i.is1_daylife, i.is1_bl_ded, i.is1_bl_d_amt, i.is1_contr2, i.is1_copay, i.is1_colim, i.is1_covrmrate, i.is1_lifeused, i.is1_covdays, i.is1_nondays, i.is1_co_used, i.is1_typary, i.is1_effdt, i.is1_covrate, i.is1_endcare, i.is1_drg, i.is1_p_name, i.is1_birth, i.is1_print, i.is1_mndays, i.is1_reim_amt, i.is1_elecbill, i.is1_elecdate, i.is1_ppscode, i.is1_psrocode, i.is1_typebill, i.is1_new_op_medicare, i.is1_netreim, i.is1_serv, i.is1_printcross, i.is1_crossdate, i.is1_filetype, i.is1_releaseinfo, i.is1_pdtype1, i.is1_pdtype2, i.is1_pdtype3, i.is1_coins, i.is1_otprim, i.is1_otins, i.is1_otset, i.is1_coveragesetby, i.is1_covcalctype, i.is1_covverified, i.is1_netcalc, i.is1_orig_expay, i.is1_orig_bl_d_amt, i.is1_orig_coamt, i.is1_orig_a_ded, i.is1_orig_drg, i.is1_orig_covdays, i.is1_excrep, i.is1_exccov, i.is1_genviaautocl, i.is1_autobill, i.is1_formver, i.is1_contract, i.is1_origin, i.is1_covgoverride, i.is1_covglogname, i.is1_covgcsnum, i.is1_excchgs, i.is1_arid, i.is1_drg_icd10 
          -> Hash (cost=14837.16..14837.16 rows=2312 width=19) (actual time=394.738..394.738 rows=2416 loops=1) 
            Output: vsub.visit_id, vsub.visit_ins, vsub.visit_arid, vsub.visit_disch_date 
            Buckets: 1024 Batches: 1 Memory Usage: 123kB 
            -> Seq Scan on public.visit vsub (cost=0.00..14837.16 rows=2312 width=19) (actual time=0.097..391.839 rows=2416 loops=1) 
             Output: vsub.visit_id, vsub.visit_ins, vsub.visit_arid, vsub.visit_disch_date 
             Filter: ((NULLIF(vsub.visit_disch_date, '0001-01-01'::date) IS NOT NULL) AND ((vsub.visit_servicecd_key)::text !~ '^[0-9]+$|[FHJbKkN\\+]'::text) AND ("left"((vsub.visit_id)::text, 1) <> ALL ('{F,P,J}'::text[])) AND (vsub.visit_mr_fdt >= (now() - '50 days'::interval)) AND (vsub.visit_mr_fdt <= (now() + '10 days'::interval))) 
             Rows Removed by Filter: 201579 
      -> Index Scan using inscomp1_pkey on public.insurance_company_table1 inscomp1 (cost=0.00..0.33 rows=1 width=11) (actual time=0.029..0.031 rows=1 loops=418) 
       Output: inscomp1.inscomp1_comp, inscomp1.inscomp1_name, inscomp1.inscomp1_addr1, inscomp1.inscomp1_addr2, inscomp1.inscomp1_city, inscomp1.inscomp1_state, inscomp1.inscomp1_zip, inscomp1.inscomp1_form, inscomp1.inscomp1_jour, inscomp1.inscomp1_prov, inscomp1.inscomp1_typebill, inscomp1.inscomp1_perdiem, inscomp1.inscomp1_diemdt, inscomp1.inscomp1_priordiem, inscomp1.inscomp1_pcused, inscomp1.inscomp1_phybillsw, inscomp1.inscomp1_approval, inscomp1.inscomp1_psro, inscomp1.inscomp1_ask_reim, inscomp1.inscomp1_reject_days, inscomp1.inscomp1_contrgl, inscomp1.inscomp1_othargl, inscomp1.inscomp1_auto_ip, inscomp1.inscomp1_auto_op, inscomp1.inscomp1_prirate, inscomp1.inscomp1_secrate, inscomp1.inscomp1_lagdays, inscomp1.inscomp1_mul1500, inscomp1.inscomp1_waitfin, inscomp1.inscomp1_opsum, inscomp1.inscomp1_write_off, inscomp1.inscomp1_transmit, inscomp1.inscomp1_detail_bl, inscomp1.inscomp1_provname, inscomp1.inscomp1_provaddr1, inscomp1.inscomp1_provaddr2, inscomp1.inscomp1_provcity, inscomp1.inscomp1_provst, inscomp1.inscomp1_provzip, inscomp1.inscomp1_cont_perc, inscomp1.inscomp1_drg_str, inscomp1.inscomp1_drg_acps, inscomp1.inscomp1_drg_dt, inscomp1.inscomp1_ub_loc2, inscomp1.inscomp1_sub_id, inscomp1.inscomp1_bcno, inscomp1.inscomp1_taxno, inscomp1.inscomp1_mcareno, inscomp1.inscomp1_mcaidno, inscomp1.inscomp1_signature, inscomp1.inscomp1_prov2, inscomp1.inscomp1_allpay, inscomp1.inscomp1_discrate, inscomp1.inscomp1_discdt, inscomp1.inscomp1_discrate2, inscomp1.inscomp1_sumitem, inscomp1.inscomp1_bank_plan, inscomp1.inscomp1_phy_1500, inscomp1.inscomp1_labmc, inscomp1.inscomp1_orer_comb, inscomp1.inscomp1_phybillex, inscomp1.inscomp1_net_reim, inscomp1.inscomp1_ask_drg, inscomp1.inscomp1_provphone, inscomp1.inscomp1_drggroup, inscomp1.inscomp1_phyins, inscomp1.inscomp1_phyub82, inscomp1.inscomp1_mnxsnf, inscomp1.inscomp1_srcpmtcde, inscomp1.inscomp1_provname2, inscomp1.inscomp1_coll_id, inscomp1.inscomp1_diagptr, inscomp1.inscomp1_tax, inscomp1.inscomp1_type_desc, inscomp1.inscomp1_revcode, inscomp1.inscomp1_arid 
       Index Cond: ((inscomp1.inscomp1_arid = vsub.visit_arid) AND ((inscomp1.inscomp1_comp)::text = (vsub.visit_ins)::text)) 
       Filter: (now() >= (vsub.visit_disch_date + ((inscomp1.inscomp1_lagdays)::double precision * '1 day'::interval))) 
    -> CTE Scan on vc (cost=0.00..0.02 rows=1 width=12) (actual time=404.481..1008.180 rows=414 loops=1) 
     Output: vc.visit_id 
    -> Index Scan using vdiag_pkey on public.visit_diagnosis vd (cost=0.00..9774.48 rows=1 width=71) (actual time=14.246..30.882 rows=1 loops=414) 
     Output: vd.vdiag_visit_key, vd.vdiag_arxseq, vd.vdiag_element, vd.vdiag_type, vd.vdiag_date, vd.vdiag_diag, vd.vdiag_arid 
     Index Cond: ((vd.vdiag_visit_key)::text = (vc.visit_id)::text) 
     Filter: ((vd.vdiag_type)::text = 'A'::text) 
     Rows Removed by Filter: 1 
Total runtime: 13796.881 ms 

EXPLAIN (ПРОАНАЛИЗИРУЙТЕ, многословный) ДЛЯ JUST ДОБИТЬСЯ ID'S ВЗЯЛ, ЧТО миллисекунды

QUERY PLAN 
Nested Loop (cost=14871.84..109244.42 rows=1 width=7) (actual time=403.659..985.167 rows=432 loops=1) 
    Output: vsub.visit_id 
    -> Nested Loop (cost=14871.84..109243.06 rows=4 width=24) (actual time=403.618..980.483 rows=441 loops=1) 
     Output: vsub.visit_id, vsub.visit_ins, vsub.visit_arid, vsub.visit_disch_date, da.da152_arid 
     Join Filter: ((vsub.visit_disch_date <= da.da152_chgdt) AND (vsub.visit_arid = da.da152_arid)) 
     Rows Removed by Join Filter: 1351 
     -> Index Scan using da152_pkey on public.da152 da (cost=0.00..10.40 rows=4 width=9) (actual time=0.004..0.014 rows=4 loops=1) 
       Output: da.da152_rel_file_key_num, da.da152_contrl, da.da152_rcdt, da.da152_chgdt, da.da152_ar_rev, da.da152_ar_rc, da.da152_ar_rcar, da.da152_unpost, da.da152_lrun, da.da152_ar_month, da.da152_insdt, da.da152_otc_rcdt, da.da152_sum_rev, da.da152_sum_rc, da.da152_sum_rcar, da.da152_begbal, da.da152_netar, da.da152_arend, da.da152_eomtrial, da.da152_rc_da, da.da152_rc_amt_otc, da.da152_rc_amt_cp, da.da152_chg_thru, da.da152_ar_ldom, da.da152_csnum, da.da152_sec_e_bill, da.da152_uform, da.da152_jform, da.da152_rate, da.da152_contract_bill, da.da152_up_front, da.da152_bad_debt, da.da152_pat_refund, da.da152_2cnd_ins, da.da152_pat_type1, da.da152_pat_type2, da.da152_pat_srvcd1_old, da.da152_pat_srvcd2_old, da.da152_wo_colcd1, da.da152_wo_alpha1s, da.da152_wo_alpha1e, da.da152_wo_colcd2, da.da152_wo_alpha2s, da.da152_wo_alpha2e, da.da152_wo_colcd3, da.da152_wo_alpha3s, da.da152_wo_alpha3e, da.da152_ins_prim, da.da152_tic_xfc1, da.da152_tic_xfc2, da.da152_ins_fc, da.da152_wo_sitnum, da.da152_wo_sit_cd, da.da152_ins2dt, da.da152_multicoqual, da.da152_multicoid, da.da152_multicodir, da.da152_multicoglnum, da.da152_pat_srvcd1, da.da152_pat_srvcd2, da.da152_adchg, da.da152_adchg_var, da.da152_month_closedt, da.da152_pat_colcd, da.da152_nonaracct, da.da152_isfup_days, da.da152_arid 
     -> Materialize (cost=14871.84..109231.85 rows=12 width=19) (actual time=100.901..244.629 rows=448 loops=4) 
       Output: vsub.visit_id, vsub.visit_ins, vsub.visit_arid, vsub.visit_disch_date 
       -> Hash Right Join (cost=14871.84..109231.79 rows=12 width=19) (actual time=403.596..976.869 rows=448 loops=1) 
        Output: vsub.visit_id, vsub.visit_ins, vsub.visit_arid, vsub.visit_disch_date 
        Hash Cond: (((i.is1_num)::text = (vsub.visit_id)::text) AND ((i.is1_ins_full)::text = (vsub.visit_ins)::text)) 
        Filter: (NULLIF(i.is1_bill_dt, '0001-01-01'::date) IS NULL) 
        Rows Removed by Filter: 2018 
        -> Seq Scan on public.insurance1 i (cost=0.00..90994.67 rows=336267 width=14) (actual time=0.002..283.076 rows=341075 loops=1) 
          Output: i.is1_num, i.is1_ins_full, i.is1_set, i.is1_prim, i.is1_stay, i.is1_direct, i.is1_admit, i.is1_disc, i.is1_from, i.is1_to, i.is1_app_sent, i.is1_app_rec, i.is1_gen_dt, i.is1_ck_dt, i.is1_contract_old, i.is1_bill_dt, i.is1_pd_dt1, i.is1_pd_amt1, i.is1_pd_dt2, i.is1_pd_amt2, i.is1_pd_dt3, i.is1_pd_amt3, i.is1_pd_status, i.is1_med_ness, i.is1_bl_furn, i.is1_bl_rep, i.is1_bl_n_rep, i.is1_bl_rate, i.is1_bl_chg, i.is1_bl_non, i.is1_coamt, i.is1_expay, i.is1_semi_rate, i.is1_diem, i.is1_cd, i.is1_typrm, i.is1_qty, i.is1_chg, i.is1_non, i.is1_opcd, i.is1_opdate, i.is1_opdesc, i.is1_opchg, i.is1_opphy, i.is1_totchg, i.is1_totnon, i.is1_maxlines, i.is1_totlines, i.is1_apc_sw, i.is1_eapc_reim, i.is1_eapc_copay, i.is1_eapc_contr, i.is1_eapc_ded, i.is1_eapc_outlr, i.is1_aapc_reim, i.is1_aapc_copay, i.is1_aapc_contr, i.is1_aapc_ded, i.is1_aapc_outlr, i.is1_mr_okayed, i.is1_mr_ok_init, i.is1_a_ded, i.is1_dayfull, i.is1_dayco, i.is1_daylife, i.is1_bl_ded, i.is1_bl_d_amt, i.is1_contr2, i.is1_copay, i.is1_colim, i.is1_covrmrate, i.is1_lifeused, i.is1_covdays, i.is1_nondays, i.is1_co_used, i.is1_typary, i.is1_effdt, i.is1_covrate, i.is1_endcare, i.is1_drg, i.is1_p_name, i.is1_birth, i.is1_print, i.is1_mndays, i.is1_reim_amt, i.is1_elecbill, i.is1_elecdate, i.is1_ppscode, i.is1_psrocode, i.is1_typebill, i.is1_new_op_medicare, i.is1_netreim, i.is1_serv, i.is1_printcross, i.is1_crossdate, i.is1_filetype, i.is1_releaseinfo, i.is1_pdtype1, i.is1_pdtype2, i.is1_pdtype3, i.is1_coins, i.is1_otprim, i.is1_otins, i.is1_otset, i.is1_coveragesetby, i.is1_covcalctype, i.is1_covverified, i.is1_netcalc, i.is1_orig_expay, i.is1_orig_bl_d_amt, i.is1_orig_coamt, i.is1_orig_a_ded, i.is1_orig_drg, i.is1_orig_covdays, i.is1_excrep, i.is1_exccov, i.is1_genviaautocl, i.is1_autobill, i.is1_formver, i.is1_contract, i.is1_origin, i.is1_covgoverride, i.is1_covglogname, i.is1_covgcsnum, i.is1_excchgs, i.is1_arid, i.is1_drg_icd10 
        -> Hash (cost=14837.16..14837.16 rows=2312 width=19) (actual time=393.928..393.928 rows=2416 loops=1) 
          Output: vsub.visit_id, vsub.visit_ins, vsub.visit_arid, vsub.visit_disch_date 
          Buckets: 1024 Batches: 1 Memory Usage: 123kB 
          -> Seq Scan on public.visit vsub (cost=0.00..14837.16 rows=2312 width=19) (actual time=0.088..391.163 rows=2416 loops=1) 
           Output: vsub.visit_id, vsub.visit_ins, vsub.visit_arid, vsub.visit_disch_date 
           Filter: ((NULLIF(vsub.visit_disch_date, '0001-01-01'::date) IS NOT NULL) AND ((vsub.visit_servicecd_key)::text !~ '^[0-9]+$|[FHJbKkN\\+]'::text) AND ("left"((vsub.visit_id)::text, 1) <> ALL ('{F,P,J}'::text[])) AND (vsub.visit_mr_fdt >= (now() - '50 days'::interval)) AND (vsub.visit_mr_fdt <= (now() + '10 days'::interval))) 
           Rows Removed by Filter: 201581 
    -> Index Scan using inscomp1_pkey on public.insurance_company_table1 inscomp1 (cost=0.00..0.33 rows=1 width=11) (actual time=0.007..0.008 rows=1 loops=441) 
     Output: inscomp1.inscomp1_comp, inscomp1.inscomp1_name, inscomp1.inscomp1_addr1, inscomp1.inscomp1_addr2, inscomp1.inscomp1_city, inscomp1.inscomp1_state, inscomp1.inscomp1_zip, inscomp1.inscomp1_form, inscomp1.inscomp1_jour, inscomp1.inscomp1_prov, inscomp1.inscomp1_typebill, inscomp1.inscomp1_perdiem, inscomp1.inscomp1_diemdt, inscomp1.inscomp1_priordiem, inscomp1.inscomp1_pcused, inscomp1.inscomp1_phybillsw, inscomp1.inscomp1_approval, inscomp1.inscomp1_psro, inscomp1.inscomp1_ask_reim, inscomp1.inscomp1_reject_days, inscomp1.inscomp1_contrgl, inscomp1.inscomp1_othargl, inscomp1.inscomp1_auto_ip, inscomp1.inscomp1_auto_op, inscomp1.inscomp1_prirate, inscomp1.inscomp1_secrate, inscomp1.inscomp1_lagdays, inscomp1.inscomp1_mul1500, inscomp1.inscomp1_waitfin, inscomp1.inscomp1_opsum, inscomp1.inscomp1_write_off, inscomp1.inscomp1_transmit, inscomp1.inscomp1_detail_bl, inscomp1.inscomp1_provname, inscomp1.inscomp1_provaddr1, inscomp1.inscomp1_provaddr2, inscomp1.inscomp1_provcity, inscomp1.inscomp1_provst, inscomp1.inscomp1_provzip, inscomp1.inscomp1_cont_perc, inscomp1.inscomp1_drg_str, inscomp1.inscomp1_drg_acps, inscomp1.inscomp1_drg_dt, inscomp1.inscomp1_ub_loc2, inscomp1.inscomp1_sub_id, inscomp1.inscomp1_bcno, inscomp1.inscomp1_taxno, inscomp1.inscomp1_mcareno, inscomp1.inscomp1_mcaidno, inscomp1.inscomp1_signature, inscomp1.inscomp1_prov2, inscomp1.inscomp1_allpay, inscomp1.inscomp1_discrate, inscomp1.inscomp1_discdt, inscomp1.inscomp1_discrate2, inscomp1.inscomp1_sumitem, inscomp1.inscomp1_bank_plan, inscomp1.inscomp1_phy_1500, inscomp1.inscomp1_labmc, inscomp1.inscomp1_orer_comb, inscomp1.inscomp1_phybillex, inscomp1.inscomp1_net_reim, inscomp1.inscomp1_ask_drg, inscomp1.inscomp1_provphone, inscomp1.inscomp1_drggroup, inscomp1.inscomp1_phyins, inscomp1.inscomp1_phyub82, inscomp1.inscomp1_mnxsnf, inscomp1.inscomp1_srcpmtcde, inscomp1.inscomp1_provname2, inscomp1.inscomp1_coll_id, inscomp1.inscomp1_diagptr, inscomp1.inscomp1_tax, inscomp1.inscomp1_type_desc, inscomp1.inscomp1_revcode, inscomp1.inscomp1_arid 
     Index Cond: ((inscomp1.inscomp1_arid = vsub.visit_arid) AND ((inscomp1.inscomp1_comp)::text = (vsub.visit_ins)::text)) 
     Filter: (now() >= (vsub.visit_disch_date + ((inscomp1.inscomp1_lagdays)::double precision * '1 day'::interval))) 
     Rows Removed by Filter: 0 
Total runtime: 985.603 ms 
+0

вы пробовали команды 'EXPLAIN SELECT ...', чтобы увидеть план запроса? Я бы попробовал использовать «ЛЮБОЙ», чтобы узнать, что произойдет. как 'SELECT, t.id_field, t2.field1 из Таблицы т LEFT JOIN t2 ON table2 t2.t_id_field = t.id_field ГДЕ t.id_field = ANY (SELECT, t.id_field из таблицы т JOIN... JOIN. WHERE <10 строк критериев фильтрации> ) ' –

+1

Пожалуйста, отредактируйте свой вопрос и добавьте планы выполнения, сгенерированные **' объяснять (анализировать, подробные) '**. [_Formatted_] (http://dba.stackexchange.com/help/formatting) ** текст **, пожалуйста, [без скриншотов] (http://meta.stackoverflow.com/questions/285551/why-may-i -not-upload-images-of-code-on-so-when-ask-a-question/285557 # 285557) –

+0

альтернативно, если ваша таблица 't' действительно большая, вы можете создать ее временную версию, индексировать ее , затем используйте это вместо –

ответ

0

Это не отвечает почему, но я надеюсь, что это поможет немного понять. Я обнаружил, что в списке:

select a from t1 where x in (select y from t2) 

прекрасно, когда в списке-низкая мощность, но, как размер списка растет, он становится менее эффективным. В отличие от этого, sem-join:

select a 
from t1 
where exists (
    select null 
    from t2.x = t2.y 
    where t1. 
) 

почти всегда эффективен для больших или малых списков.

Из-за лени, я использовал список в своем первом взломе и почти постоянно сожалел об этом. Когда я переключаюсь на полусоединение, мир, как и должно быть.

Итак, можете ли вы попытаться изменить свой запрос на это и посмотреть, что произойдет?

select t.id_field, t2.field1 from table t 
LEFT JOIN table2 t2 ON t2.t_id_field = t.id_field 
WHERE exists (
    select 1 
    from table tt 
    join . . . 
    join . . . 
    where 
    t.id_field = tt.id_field and 
    <10 rows of filtering criteria> 
) 

И ясно, разница между Полусоединением и присоединиться, что если в-списка содержит повторы, пол присоединиться игнорирует последующие вхождения. Он не только не умножает результаты строк, но и «останавливается» для каждого матча.

Но что касается вашего основного вопроса - можете ли вы довести это до первоначальной трех секунд? Я сомневаюсь в этом, потому что я подозреваю, что внутренний запрос - это то, откуда пришли дополнительные девять секунд.

- EDIT -

Это может быть больше кода, чем вы готовы иметь дело с, чтобы спасти девять секунд, но то, что происходит, когда вы запускаете это?

CREATE OR REPLACE FUNCTION test() 
    RETURNS TABLE (
    id_field varchar, 
    field1 varchar 
) AS 
$BODY$ 
    DECLARE 
    id_field_list varchar[]; 
    BEGIN 
    SELECT array_agg (t.id_field) 
    into id_field_list 
    from table t 
    JOIN . . . 
    JOIN . . .  
    WHERE <10 rows of filtering criteria>; 

    return query 
    select t.id_field, t2.field1 from table t 
    LEFT JOIN table2 t2 ON t2.t_id_field = t.id_field 
    WHERE t.id_field = any(id_field_list); 
    END 
$BODY$ 
LANGUAGE plpgsql; 

и, конечно же, вы получите результаты запроса от:

select * from test(); 
+0

Путь Exists занимает более 20 секунд. Вы упомянули, что внутренний запрос занимает дополнительные девять секунд, но он работает менее чем за секунду, но почему он занимает гораздо больше времени? Логически критерии фильтрации занимают менее секунды, а таблица запросов2 с введенным вручную идентификатором занимает 3 секунды, поэтому было бы разумно подумать, что мы могли бы запросить данные по крайней мере на 4 секунды. –

+0

Это любопытно ... и неожиданно. Я добавил функцию к моему ответу, точно так же, как и для экземпляра, чтобы увидеть, получит ли он ожидаемые результаты. По существу, это должно делать то, что вы делали вручную, только в один шаг. Даже если он дает желаемые результаты, он не объясняет ваш основной вопрос, и, опять же, это может быть больше, чем вы готовы справиться, чтобы сбрить несколько секунд. – Hambone

+0

Благодарим вас за эту функцию, но у меня есть доступ только для чтения, что усложняет задачу. Я обновил исходное сообщение с помощью загнутого запроса, который показывает проблему с скоростью, чтобы вы могли видеть, как я действительно пишу свой запрос, и убедитесь, что я не делаю что-то странное. –

1

полное переписывание запроса:

  • только удерживающего визита и диагностики таблицы во внешнем запросе
  • перемещение остальных столов (которые используются только в качестве условий) в EXISTS() фразы
  • переписав NULLIF(a,b) IS NULL к a > b, так как b, как представляется, Н/Значение сторожевого (Я хотел бы предложить -infinity для этого, или просто NULL)
  • и изменил один LEFT JOIN ... NULL к NOT EXISTS(...) конструкции.
  • непроверенных , так как я не имею определения таблицы

WITH vCriteria AS (
    SELECT vs.visit_id, vd.vdiag_diag 
    FROM visit vs 
    LEFT JOIN visit_diagnosis vd ON vd.vdiag_visit_key = vs.visit_id 
    WHERE EXISTS (SELECT * 
     FROM da152 da 
     WHERE da.da152_arid = vs.visit_arid 
     AND vs.visit_disch_date <= da.da152_chgdt 
     ) 
    AND EXISTS (SELECT * 
     FROM insurance_company_table1 ict 
     WHERE ict.inscomp1_comp = vs.visit_ins 
     AND ict.inscomp1_arid = vs.visit_arid 
     AND Now() >= (vs.visit_disch_date + ict.inscomp1_lagdays * INTERVAL '1 day') 
     ) 
    AND NOT EXISTS (
     SELECT * 
     FROM insurance1 ins 
     WHERE ins.is1_num = vs.visit_id AND ins.is1_ins_full = vs.visit_ins 
     AND ins.is1_bill_dt > '0001-01-01'::date 
     ) 
    AND vs.visit_mr_fdt 
     BETWEEN (now() - 50 * INTERVAL '1 day') AND (now() + 10 * INTERVAL '1 day') 
    AND vs.visit_disch_date > '0001-01-01'::date 
    AND vs.visit_servicecd_key ~ '^[0-9]+$|[FHJbKkN\\+]' = false 
    AND LEFT (vs.visit_id, 1) NOT IN ('F', 'P', 'J') 
) 
SELECT vCriteria.* FROM vCriteria 
     ;