sql优化

问题SQL!!(开发上观察到的)

SELECT
    stock.stockbike_id,
    stock.b_s_name_i_n AS b_s_name_i_n,
    stock.nenshiki_t_no_n,
    stock.soukou_n,
    stock.normal_flag,
    stock.one_owner_flag,
    stock.guarantee_flag,
    stock.repair_flag,
    stock.b_m_name_n,
    stock.b_iro_n,
    stock.iro_index,
    stock.kakaku,
    stock.kakaku_n,
    (case when trim(stock.total_price) = '0' then '' else trim(stock.total_price) end) AS total_price,
    (case when trim(stock.total_price_n) = '0万円' then '' else trim(stock.total_price_n)end) AS total_price_n,
    stock.syaken_n,
    stock.haiki_n,
    stock.hoken_n,
    stock.fukabun_n,
    stock.fukabun_n_web,
    (
        SELECT
            trim(movie_name)
        FROM
            stockbike_movie
        WHERE
                stockbike_movie.stockbike_id = stock.stockbike_id
    ) AS movie_name,
    (case when stockbike_movie.movie_name IS null then 2 else 1 end ) AS sort_movie,
    stock.chatch_n,
    stock.ec_flag,
    client.client_print_name,
    client.address1,
    client.phone11,
    client.fax1,
    client.zip,
    stock.pre_n,
    area_master.area_name,
    stock.area_id ,
    stock.subarea_id ,
    stock.no_photo_00 ,
    stock.options,
    stock.kyabu_fi_flag,
    stock.suto_flag,
    stock.hid_flag,
    stock.etc_flag,
    stock.boaup_flag,
    stock.mt_at_flag,
    stock.campaign_flag,
    client.shop_mail,
    stock.keisai,
    REPLACE(REPLACE(b_syasyu.b_s_name_i_r , '&','_'), '__','_' ) AS syasyu_dir,
    REPLACE(REPLACE(b_maker.b_m_name_i_r , '&','_'), '__','_' ) AS b_m_name_i_r,
    stock.client_id AS client_id,
    case when stock.soukou_n = '未記入' then '0' when stock.soukou_n = '走不明' then '1' else '2' end || repeat('0', 10-octet_length(regexp_replace(stock.soukou_n, '(,|K)', '','g'))) || regexp_replace(stock.soukou_n, '(,|K)', '','g') AS soukou_sort ,
    case when stock.soukou_n = '未記入' then '2' when stock.soukou_n = '—' then '2' when stock.soukou_n = '走不明' then '1' else '0' end AS soukou_sort_new ,
    case when stock.nenshiki_t_no_n = '新車' then '2' when stock.nenshiki_t_no_n = '—' then '8' when stock.nenshiki_t_no_n = '年式不明' then '9' else '1' end || repeat('0', 10-octet_length(stock.nenshiki_t_no_n)) || stock.nenshiki_t_no_n AS nenshiki_sort,
    case when stock.nenshiki_t_no_n = '—' then '9' when stock.nenshiki_t_no_n = '年式不明' then '8' else '1' end AS nenshiki_sort_new ,
    (CASE WHEN stock.kakaku_n = 'ASK' THEN '1' ELSE '0' END) AS kakaku_sort_new,
    (CASE WHEN stock.kakaku_n = 'ASK' THEN 999999999 ELSE float4(stock.kakaku) END) AS kakaku_sort,
    (CASE WHEN trim(stock.total_price) = '' THEN '1' WHEN trim(stock.total_price)='0' THEN '1' ELSE '0' END) AS total_price_sort_new,
    (CASE WHEN length(trim(total_price)) > 0 THEN float4 (stock.total_price) ELSE null END) AS total_price_sort,
    (case when new_flag = 2
    AND ( trim(total_price) <>''
    AND total_price IS NOT null) then '6' when new_flag = 2
    AND ( trim(total_price) =''
    OR  total_price IS null) then '5' when new_flag = 1
    AND ( trim(total_price) <>''
    AND total_price IS NOT null) then '4' when new_flag = 0
    AND ( trim(total_price) <>''
    AND total_price IS NOT null) then '3' when new_flag = 1
    AND ( trim(total_price) =''
    OR  total_price IS null) then '2' when new_flag = 0
    AND ( trim(total_price) =''
    OR  total_price IS null) then '1' end) AS total_price_sort_all,
    CASE WHEN stock.ec_flag = '1' THEN '1' ELSE '0' END AS ec_sort,
    stock.tax_flag ,
    stock.m_b_flag AS m_b_stock_flag ,
    client.m_b_flag AS m_b_client_flag,
    stock.maker_id AS maker_id,
    stock.syasyu_id AS syasyu_id,
    b_syasyu.genre_ids,
    stock.goopon_flag,
    b_syasyu.b_s_name_j,
    to_char(stock.koushin, 'YYYY-MM-DD') AS koushin,
    stock.no_photo_00,
    stock.new_flag,
    stock.syuuhuku_flag,
    stock.seizou_kuni,
    j.jititai_name,
    (case when matched_appraisal.stockbike_id !='' then 1 else 0 end ) AS jba_stock_flag,
    (case when matched_appraisal.stockbike_id !=''
    AND stock.new_flag = 2 then 4 when matched_appraisal.stockbike_id !='' then 3 when stock.new_flag = 2 then 2 else 1 end ) AS jba_sort,
    matched_appraisal.nearfoot_score,
    matched_appraisal.frame_score,
    matched_appraisal.engine_score,
    matched_appraisal.appearance_score,
    extract(year FROM matched_appraisal.appraisal_date)AS appraisal_year,
    extract(month FROM matched_appraisal.appraisal_date)AS appraisal_month,
    extract(day FROM matched_appraisal.appraisal_date)AS appraisal_day,
    matched_appraisal.appraisal_date ,
    CASE substring(stock.m_b_flag, 2) WHEN '1' THEN 2 WHEN '2' THEN 2 ELSE 1 END AS mitsumori ,
    CASE WHEN stock.no_photo_00 > 1 THEN '1' ELSE '0' END AS no_photo_00_sort
FROM stock 
INNER JOIN client ON stock.client_id = client.client_id
INNER JOIN b_syasyu ON stock.syasyu_id = b_syasyu.syasyu_id
INNER JOIN b_maker ON b_syasyu.maker_id = b_maker.maker_id
INNER JOIN area_master ON client.area_id = area_master.area_id
INNER JOIN jititai_area_master j ON client.address_code = j.jititai_id
LEFT JOIN stockbike_movie ON stockbike_movie.stockbike_id = stock.stockbike_id
LEFT JOIN matched_appraisal ON stock.stockbike_id = matched_appraisal.stockbike_id AND matched_appraisal.frame_no = stock.frame_no
WHERE
        stock.stockbike_id != ''
ORDER BY
    jba_stock_flag DESC ,
    total_price_sort_all DESC ,
    no_photo_00_sort DESC ,
    sort_movie ASC ,
    ec_sort DESC ,
    mitsumori DESC ,
    kakaku_sort_new ASC ,
    kakaku_sort DESC ,
    nenshiki_sort_new ASC,
    nenshiki_sort DESC ,
    soukou_sort_new ASC,
    soukou_sort ASC ,
    stock.up_date DESC 
LIMIT 50 
OFFSET 0

问题1:

(
        SELECT
            trim(movie_name)
        FROM
            stockbike_movie
        WHERE
                stockbike_movie.stockbike_id = stock.stockbike_id
    ) AS movie_name,

这个是慢的主因之一。把这个改成
trim(movie_name) movie_name,

SQL可以快一半!!

问题2:

(case when matched_appraisal.stockbike_id !='' then 1 else 0 end ) AS jba_stock_flag,
(case when matched_appraisal.stockbike_id !='' AND stock.new_flag = 2 then 4 when matched_appraisal.stockbike_id !='' then 3 when stock.new_flag = 2 then 2 else 1 end ) AS jba_sort,

其中

matched_appraisal.stockbike_id !=''

这个不可能是FALSE的!!

问题3:

stock.no_photo_00

这个字段被取了两人次。

优化考虑

去掉所有与排序无关的内容后:

SELECT 
     row_number() over () ordinal,
     *
FROM (
    SELECT
         stock.stockbike_id,
        stock.ec_flag,
        stock.no_photo_00 ,
        (case when stockbike_movie.movie_name IS null then 2 else 1 end ) AS sort_movie,
        case when stock.soukou_n = '未記入' then '0' when stock.soukou_n = '走不明' then '1' else '2' end || repeat('0', 10-octet_length(regexp_replace(stock.soukou_n, '(,|K)', '','g'))) || regexp_replace(stock.soukou_n, '(,|K)', '','g') AS soukou_sort ,
        case when stock.soukou_n = '未記入' then '2' when stock.soukou_n = '—' then '2' when stock.soukou_n = '走不明' then '1' else '0' end AS soukou_sort_new ,
        case when stock.nenshiki_t_no_n = '新車' then '2' when stock.nenshiki_t_no_n = '—' then '8' when stock.nenshiki_t_no_n = '年式不明' then '9' else '1' end || repeat('0', 10-octet_length(stock.nenshiki_t_no_n)) || stock.nenshiki_t_no_n AS nenshiki_sort,
        case when stock.nenshiki_t_no_n = '—' then '9' when stock.nenshiki_t_no_n = '年式不明' then '8' else '1' end AS nenshiki_sort_new ,
        (CASE WHEN stock.kakaku_n = 'ASK' THEN '1' ELSE '0' END) AS kakaku_sort_new,
        (CASE WHEN stock.kakaku_n = 'ASK' THEN 999999999 ELSE float4(stock.kakaku) END) AS kakaku_sort,
        (case 
            when new_flag = 2 AND ( trim(total_price) <>'' AND total_price IS NOT null)    then '6' 
            when new_flag = 2 AND ( trim(total_price) = '' OR  total_price IS null)            then '5' 
            when new_flag = 1 AND ( trim(total_price) <>'' AND total_price IS NOT null)     then '4' 
            when new_flag = 0 AND ( trim(total_price) <>'' AND total_price IS NOT null)     then '3' 
            when new_flag = 1 AND ( trim(total_price) = '' OR  total_price IS null)         then '2' 
            when new_flag = 0 AND ( trim(total_price) = '' OR  total_price IS null)         then '1'
            end) AS total_price_sort_all,
        CASE WHEN stock.ec_flag = '1' THEN '1' ELSE '0' END AS ec_sort,
        matched_appraisal.nearfoot_score,
        matched_appraisal.frame_score,
        matched_appraisal.engine_score,
        matched_appraisal.appearance_score,
        matched_appraisal.appraisal_date ,
        (case when matched_appraisal.stockbike_id !='' then 1 else 0 end ) AS jba_stock_flag,
        CASE substring(stock.m_b_flag, 2) WHEN '1' THEN 2 WHEN '2' THEN 2 ELSE 1 END AS mitsumori,
        CASE WHEN stock.no_photo_00 > 1 THEN '1' ELSE '0' END AS no_photo_00_sort
    FROM stock 
    LEFT JOIN stockbike_movie ON stockbike_movie.stockbike_id = stock.stockbike_id
    LEFT JOIN matched_appraisal ON stock.stockbike_id = matched_appraisal.stockbike_id AND matched_appraisal.frame_no = stock.frame_no
    WHERE
            stock.stockbike_id != ''
    ORDER BY
        jba_stock_flag DESC ,
        total_price_sort_all DESC ,
        no_photo_00_sort DESC ,
        sort_movie ASC ,
        ec_sort DESC ,
        mitsumori DESC ,
        kakaku_sort_new ASC ,
        kakaku_sort DESC ,
        nenshiki_sort_new ASC,
        nenshiki_sort DESC ,
        soukou_sort_new ASC,
        soukou_sort ASC ,
        stock.up_date DESC 
    LIMIT 50 
    OFFSET 0
) tmpr_search_result_base
;

执行时间对比:

优化前:5233.765 ms
优化后:1255.147 ms

优化解决方案

SELECT
    stock.stockbike_id,
    stock.b_s_name_i_n AS b_s_name_i_n,
    stock.nenshiki_t_no_n,
    stock.soukou_n,
    stock.normal_flag,
    stock.one_owner_flag,
    stock.guarantee_flag,
    stock.repair_flag,
    stock.b_m_name_n,
    stock.b_iro_n,
    stock.iro_index,
    stock.kakaku,
    stock.kakaku_n,
    (case when trim(stock.total_price) = '0' then '' else trim(stock.total_price) end) AS total_price,
    (case when trim(stock.total_price_n) = '0万円' then '' else trim(stock.total_price_n)end) AS total_price_n,
    stock.syaken_n,
    stock.haiki_n,
    stock.hoken_n,
    stock.fukabun_n,
    stock.fukabun_n_web,
    trim(movie_name) AS movie_name,
    sort_movie,
    stock.chatch_n,
    stock.ec_flag,
    client.client_print_name,
    client.address1,
    client.phone11,
    client.fax1,
    client.zip,
    stock.pre_n,
    area_master.area_name,
    stock.area_id ,
    stock.subarea_id ,
    stock.no_photo_00 ,
    stock.options,
    stock.kyabu_fi_flag,
    stock.suto_flag,
    stock.hid_flag,
    stock.etc_flag,
    stock.boaup_flag,
    stock.mt_at_flag,
    stock.campaign_flag,
    client.shop_mail,
    stock.keisai,
    REPLACE(REPLACE(b_syasyu.b_s_name_i_r , '&','_'), '__','_' ) AS syasyu_dir,
    REPLACE(REPLACE(b_maker.b_m_name_i_r , '&','_'), '__','_' ) AS b_m_name_i_r,
    stock.client_id AS client_id,
    soukou_sort ,
    soukou_sort_new ,
    nenshiki_sort,
    nenshiki_sort_new ,
    kakaku_sort_new,
    kakaku_sort,
    (CASE WHEN trim(stock.total_price) = '' THEN '1' WHEN trim(stock.total_price)='0' THEN '1' ELSE '0' END) AS total_price_sort_new,
    (CASE WHEN length(trim(total_price)) > 0 THEN float4 (stock.total_price) ELSE null END) AS total_price_sort,
    total_price_sort_all,
    ec_sort,
    stock.tax_flag ,
    stock.m_b_flag AS m_b_stock_flag ,
    client.m_b_flag AS m_b_client_flag,
    stock.maker_id AS maker_id,
    stock.syasyu_id AS syasyu_id,
    b_syasyu.genre_ids,
    stock.goopon_flag,
    b_syasyu.b_s_name_j,
    to_char(stock.koushin, 'YYYY-MM-DD') AS koushin,
    stock.no_photo_00,
    stock.new_flag,
    stock.syuuhuku_flag,
    stock.seizou_kuni,
    j.jititai_name,
    jba_stock_flag,
    (case when matched_appraisal.stockbike_id !=''
    AND stock.new_flag = 2 then 4 when matched_appraisal.stockbike_id !='' then 3 when stock.new_flag = 2 then 2 else 1 end ) AS jba_sort,
    matched_appraisal.nearfoot_score,
    matched_appraisal.frame_score,
    matched_appraisal.engine_score,
    matched_appraisal.appearance_score,
    extract(year FROM matched_appraisal.appraisal_date)AS appraisal_year,
    extract(month FROM matched_appraisal.appraisal_date)AS appraisal_month,
    extract(day FROM matched_appraisal.appraisal_date)AS appraisal_day,
    matched_appraisal.appraisal_date ,
    mitsumori ,
    no_photo_00_sort
FROM (
    SELECT 
         row_number() over () ordinal,
         *
    FROM (
        SELECT
             stock.stockbike_id,
            stock.ec_flag,
            stock.no_photo_00 ,
            (case when stockbike_movie.movie_name IS null then 2 else 1 end ) AS sort_movie,
            case when stock.soukou_n = '未記入' then '0' when stock.soukou_n = '走不明' then '1' else '2' end || repeat('0', 10-octet_length(regexp_replace(stock.soukou_n, '(,|K)', '','g'))) || regexp_replace(stock.soukou_n, '(,|K)', '','g') AS soukou_sort ,
            case when stock.soukou_n = '未記入' then '2' when stock.soukou_n = '—' then '2' when stock.soukou_n = '走不明' then '1' else '0' end AS soukou_sort_new ,
            case when stock.nenshiki_t_no_n = '新車' then '2' when stock.nenshiki_t_no_n = '—' then '8' when stock.nenshiki_t_no_n = '年式不明' then '9' else '1' end || repeat('0', 10-octet_length(stock.nenshiki_t_no_n)) || stock.nenshiki_t_no_n AS nenshiki_sort,
            case when stock.nenshiki_t_no_n = '—' then '9' when stock.nenshiki_t_no_n = '年式不明' then '8' else '1' end AS nenshiki_sort_new ,
            (CASE WHEN stock.kakaku_n = 'ASK' THEN '1' ELSE '0' END) AS kakaku_sort_new,
            (CASE WHEN stock.kakaku_n = 'ASK' THEN 999999999 ELSE float4(stock.kakaku) END) AS kakaku_sort,
            (case 
                when new_flag = 2 AND ( trim(total_price) <>'' AND total_price IS NOT null)    then '6' 
                when new_flag = 2 AND ( trim(total_price) = '' OR  total_price IS null)            then '5' 
                when new_flag = 1 AND ( trim(total_price) <>'' AND total_price IS NOT null)     then '4' 
                when new_flag = 0 AND ( trim(total_price) <>'' AND total_price IS NOT null)     then '3' 
                when new_flag = 1 AND ( trim(total_price) = '' OR  total_price IS null)         then '2' 
                when new_flag = 0 AND ( trim(total_price) = '' OR  total_price IS null)         then '1'
                end) AS total_price_sort_all,
            CASE WHEN stock.ec_flag = '1' THEN '1' ELSE '0' END AS ec_sort,
            (case when matched_appraisal.stockbike_id !='' then 1 else 0 end ) AS jba_stock_flag,
            CASE substring(stock.m_b_flag, 2) WHEN '1' THEN 2 WHEN '2' THEN 2 ELSE 1 END AS mitsumori,
            CASE WHEN stock.no_photo_00 > 1 THEN '1' ELSE '0' END AS no_photo_00_sort
        FROM stock 
        LEFT JOIN stockbike_movie ON stockbike_movie.stockbike_id = stock.stockbike_id
        LEFT JOIN matched_appraisal ON stock.stockbike_id = matched_appraisal.stockbike_id AND matched_appraisal.frame_no = stock.frame_no
        WHERE
                stock.stockbike_id != ''
        ORDER BY
            jba_stock_flag DESC ,
            total_price_sort_all DESC ,
            no_photo_00_sort DESC ,
            sort_movie ASC ,
            ec_sort DESC ,
            mitsumori DESC ,
            kakaku_sort_new ASC ,
            kakaku_sort DESC ,
            nenshiki_sort_new ASC,
            nenshiki_sort DESC ,
            soukou_sort_new ASC,
            soukou_sort ASC ,
            stock.up_date DESC 
        LIMIT 50 
        OFFSET 0
    ) tmpr_search_result_base
) tmpr_search_result_preordered
INNER JOIN stock ON tmpr_search_result_preordered.stockbike_id=stock.stockbike_id
INNER JOIN client ON stock.client_id = client.client_id
INNER JOIN b_syasyu ON stock.syasyu_id = b_syasyu.syasyu_id
INNER JOIN b_maker ON b_syasyu.maker_id = b_maker.maker_id
INNER JOIN area_master ON client.area_id = area_master.area_id
INNER JOIN jititai_area_master j ON client.address_code = j.jititai_id
LEFT JOIN stockbike_movie ON stockbike_movie.stockbike_id = stock.stockbike_id
LEFT JOIN matched_appraisal ON stock.stockbike_id = matched_appraisal.stockbike_id AND matched_appraisal.frame_no = stock.frame_no
ORDER BY
    ordinal
;

执行时间:1390.912 ms

提速倍率:3.762829712倍

注意事项

修改文件时不要复制上面的语句。最好再改一遍。
我调试时用的是UTF8,转码后可能会有一些转不回EUC-JP的字符。

你可能感兴趣的:(sql优化)