分区表上的Oracle SQL高效查询:“逐个案例”

时间:2014-01-14 21:04:06

标签: sql performance oracle

我在密钥date_insert上分区了大约100亿条记录。

MY_BIG_TABLE

  • id NUMERIC二级索引
  • date_insert DATE主索引
  • date_fact DATE二级索引
  • 数据BLOB

输入:

  • :date_input1
  • :date_input2
  • :date_input3
  • :ID

注意::date_input1 < :date_input2

我想要

  1. IF date_fact < :date_input_1按date_fact DESC
  2. 排序的第一行
  3. ELSE IF date_fact < :date_input_2按date_fact ASC
  4. 排序的第一行
  5. ELSE最新的
  6. 查询原型应该是:

    SELECT date_insert, date_fact, data (
    
            SELECT
                date_insert, 
                date_fact,
                CASE 
                   WHEN (date_fact < :date_input_1 AND id= :id) : 2
                   WHEN (date_fact < :date_input_2 AND id= :id) : 1
                   ELSE : 0  
                check,
    
                CASE 
                   WHEN (date_fact < :date_input_1 AND id= :id) : NULL
                   WHEN (date_fact < :date_input_2 AND id= :id) : data
                   ELSE : NULL  
                data
    
            FROM MY_BIG_TABLE
            WHERE date_insert > :date_input3   
            order by check, DECODE(check, 1, date_fact) ASC,
                            date_fact DESC 
    
    ) WHERE ROWNUM <2
    

    我需要做这项艰苦的工作,以避免过多访问此表。 要完全重建查询的任何建议更简单,更容易吗?

1 个答案:

答案 0 :(得分:4)

你只想找一排。那么,做三个不同的子查询,每个子查询一行,然后选择你想要的那个:

select date_insert, date_fact, data
from (select date_insert, date_fact, data
      from ((select date_insert, date_fact, data, 2 as check
             from (select date_insert, date_fact,
                          (CASE WHEN (date_fact < :date_input_1 AND id= :id) then NULL
                                WHEN (date_fact < :date_input_2 AND id= :id) then data
                                ELSE NULL
                           end) as data
                   from MY_BIG_TABLE
                   where date_fact < :date_input_1 and date_insert > :date_input3
                   order by date_fact desc
                  ) t
             where rownum = 1
            ) union all
            (select date_insert, date_fact, data, 1 as check
             from (select date_insert, date_fact,
                          (CASE WHEN (date_fact < :date_input_1 AND id= :id) then NULL
                                WHEN (date_fact < :date_input_2 AND id= :id) then data
                                ELSE NULL
                           end) as data
                   from MY_BIG_TABLE
                   where date_fact < :date_input_2 and date_insert > :date_input3
                   order by date_fact asc
                  ) t
             where rownum = 1
            ) union all
            (select date_insert, date_fact, data, 0 as check
             from (select date_insert, date_fact,
                          (CASE WHEN (date_fact < :date_input_1 AND id= :id) then NULL
                                WHEN (date_fact < :date_input_2 AND id= :id) then data
                                ELSE NULL
                           end) as data
                   from MY_BIG_TABLE
                   where date_insert > :date_input3
                   order by date_fact desc
                  ) t
             where rownum = 1
            )
           ) t
      order by check desc
     ) t
where rownum = 1;

Oracle应该足够聪明,可以使用子查询的索引,因此这可能实际上运行得非常快。