Oracle сортирует вложенный запрос и rownum - PullRequest
0 голосов
/ 01 сентября 2011

У меня есть запрос, который занимает слишком много. Это работает 10g экземпляр Oracle. TABLE_A имеет 30 000 000 строк. TABLE_B имеет 300 000 строк.

SELECT A.F1, A.F2, B.F1
  FROM (  SELECT A.F1, A.F2, B.F1
          FROM TABLE_A A LEFT JOIN TABLE_B B ON A.ID_B = B.ID_B
          WHERE A.F3 = ? AND A.F4 = ?
        ORDER BY B.F1)
 WHERE ROWNUM < 100

Я пытался создать представление:

CREATE VIEW TABLE_B_SORTED AS SELECT * FROM TABLE_B ORDER BY F1

изменив запрос таким образом

SELECT A.F1, A.F2, B.F1
  FROM (  SELECT A.F1, A.F2, B.F1
          FROM TABLE_A A LEFT JOIN TABLE_B_SORTED B ON A.ID_B = B.ID_B
          WHERE A.F3 = ? AND A.F4 = ?
       )
 WHERE ROWNUM < 100

но заказ не обслуживается.

Я также пытался изменить запрос таким образом

SELECT A.F1, A.F2, T.F1
  FROM (  SELECT A.F1, A.F2, T.F1
          FROM TABLE_A A LEFT JOIN (SELECT * FROM TABLE_B B ORDER BY B.F1 ) T ON A.ID_B = T.ID_B
          WHERE A.F3 = ? AND A.F4 = ?
       )
 WHERE ROWNUM < 100

но заказ не обслуживается.

Есть предложения?

Plan
SELECT STATEMENT  ALL_ROWSCost: 8.943  Bytes: 2.871  Cardinality: 99                        
    7 COUNT STOPKEY                      
        6 VIEW MY_SCHEMA. Cost: 8.943  Bytes: 146.247  Cardinality: 5.043                  
            5 SORT ORDER BY STOPKEY  Cost: 8.943  Bytes: 226.935  Cardinality: 5.043              
                4 HASH JOIN OUTER  Cost: 8.881  Bytes: 226.935  Cardinality: 5.043          
                    2 TABLE ACCESS BY INDEX ROWID TABLE TABLE_A Cost: 8.117  Bytes: 172.725  Cardinality: 4.935      
                        1 INDEX RANGE SCAN INDEX I_TABLE_A Cost: 27  Cardinality: 10.166  
                    3 TABLE ACCESS FULL TABLE TABLE_B Cost: 758  Bytes: 2.791.520  Cardinality: 279.152

1 Ответ

0 голосов
/ 01 сентября 2011

Возможно, вам следует создать восходящий индекс на b.f1, если ваш запрос занимает слишком много времени.

Кроме того, если вы выполняете LEFT JOIN, это означает, что у вас могут быть значения NULL в B. Вы хотите, чтобы они были первыми или последними?

Вероятно, вам лучше сделать:

   SELECT /*+ first_rows_100 */ -- do not hesitate to use Oracle hints!
          a.f1, a.f2, b.f1
     FROM table_b b
    INNER JOIN table_a a
       ON a.id_b = b.id_b
    WHERE a.f3 = ? and a.f4 = ?
    ORDER BY b.f1 ASC

Кроме того, заказ источника соединения полностью бесполезен (второй и третий запрос). Присоединение никогда не гарантирует, что результирующие строки сохранят порядок, в котором они находятся в исходных таблицах.

...