Как оптимизировать такой селект ?

razliv
Дата: 20.11.2009 11:27:20
есть селект такого вида:


SELECT first_col
  FROM (SELECT   first_col
            FROM (SELECT first_col
                    FROM test
                  UNION ALL
                  SELECT first_col
                    FROM test_another
                  UNION ALL
                  SELECT first_col
                    FROM test_third)
        ORDER BY DBMS_RANDOM.VALUE)
 WHERE ROWNUM < 10


Нам нужно выбрать случайные значения из запроса. Причем количество случаных строк очень мало относительно самого слекта. То есть вот этот селект:

SELECT first_col
                    FROM test
                  UNION ALL
                  SELECT first_col
                    FROM test_another
                  UNION ALL
                  SELECT first_col
                    FROM test_third)

выбирает скажем 700 тысяч строк, затем произвольно сортирует и берет десять. И занимает это времени само собой не кисло. Как бы ускорить этот запрос ?
Elic
Дата: 20.11.2009 11:38:09
razliv
Дата: 20.11.2009 11:46:18
Elic

Спасибо большое Элик ! Выручили уже в который раз!
suPPLer
Дата: 20.11.2009 11:49:45
Elic
RTFM sample_clause (FAQ)


Только с процентом придётся экспериментировать для каждой таблицы, если данные неравномерно распределены (напр., в первой 650000 строк, во второй - 49000, в третьей - 1000)...
razliv
Дата: 20.11.2009 12:03:11
Когда соединяешь пару таблиц не пашет сампле :(

SAMPLE option not allowed in statement with multiple table references
suPPLer
Дата: 20.11.2009 12:06:08
razliv
Когда соединяешь пару таблиц не пашет сампле :(

SAMPLE option not allowed in statement with multiple table references


Вам Elic ссылку дал на синтаксис - Вы её внимательно посмотрели? Добавляйте инструкцию sample к каждой таблице в объединении (между которыми UNION ALL стоят).
razliv
Дата: 20.11.2009 12:09:12
Sappler

То что я написал селект, это в упрошенном виде :(
На самом деле каждая таблица тест - это джойн парочки таблиц.
У меня база 9i, а сампле когда пару таблиц джойнены - только в 10g работают ;(
impslayer
Дата: 20.11.2009 12:11:09
если тебе нужно только 10 строк, то зачем делать выборку всех строк, кто мешает создать курсор типа этого и выбирать по превичному ключу:
declare
v_counter number;
v_max_index_val number;
v_random_val number;
v_value varchar2(256);
begin
select
max(id)
into v_max_index_val
from table;
v_counter := 0;
while true != false
loop
v_random_val := trunc(dbms_random.value * v_max_index_val);
select case when exists(
select 1 from table
where id = v_random_val)
then '1' else '0' end
into v_value
from dual;
if v_value = '1' then
select id
into v_value
from table
where id = v_random_val;
dbms_output.put_line(v_value);
v_counter := v_counter + 1;
end if;
if v_counter > 9
then exit;
end if;
end loop;
end;
suPPLer
Дата: 20.11.2009 12:14:08
razliv,

заворачивайте каждый подзапрос с соединением в
select ... from (... order by dbms_random.value) where rownum < 11
Правда, так у Вас будет не совсем случайная выборка, поскольку вероятность получить все строки из определённого подзапроса станет одинаковой для каждого подзапроса.
suPPLer
Дата: 20.11.2009 12:20:25
impslayer
если тебе нужно только 10 строк, то зачем делать выборку всех строк, кто мешает создать курсор типа этого и выбирать по превичному ключу:
...


И айдишники у всех числа "в обязательном порядке", и ускорить это может "невероятно", и PL/SQL тут явно "необходим"...