Выберите различное… внутреннее соединение против выбора… где идентификатор в (…)
Я пытаюсь создать подмножество таблицы (как материализованное представление), определенное как те записи, которые имеют соответствующую запись в другом материализованном представлении.
Например, допустим, у меня есть таблица Users с столбцами user_id и name, а также таблица Log с столбцами entry_id, user_id, activity и timestamp.
Сначала я создаю материализованное представление таблицы Log, выбирая только те строки с меткой времени> some_date. Теперь я хочу получить materliazed представление о пользователях, на которые есть ссылка в моем снимке таблицы журнала. Я могу либо создать его как
select * from Users where user_id in (select user_id from Log_mview)
или я могу сделать
select distinct u.* from Users u inner join Log_mview l on u.user_id = l.user_id
(нужен отчет, чтобы избежать нескольких попаданий пользователей с несколькими записями в журнале).
Первый кажется чище и элегантнее, но занимает гораздо больше времени. Я что-то пропустил? Есть лучший способ сделать это?
Изменить:where exists
положение очень помогло, за исключением случая, когда условие используетOR
, Например, предположим, что в приведенной выше таблице журнала также имеется столбец user_name, и правильный способ сопоставления записи журнала с записью Users - это когда один из столбцов (идентификатор пользователя или имя пользователя) совпадает. Я нахожу это
select distinct u.* from Users u
inner join Log_mview l
on u.user_id = l.user_id or u.name = l.user_name
намного быстрее чем
select * from Users u where exists
(select id from Log_mview l
where l.user_id = u.user_id or l.user_name = u.name)
Любая помощь?
(Что касается плана объяснения ... Позвольте мне поработать над его дезинфекцией или, скорее, их ... я опубликую их через некоторое время.)
Изменить: объяснить планы: Для запроса с внутренним объединением:
Plan hash value: 436698422 --------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | --------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 4539K| 606M| | 637K (3)| 02:07:25 | | 1 | HASH UNIQUE | | 4539K| 606M| 3201M| 637K (3)| 02:07:25 | | 2 | CONCATENATION | | | | | | | |* 3 | HASH JOIN | | 4206K| 561M| 33M| 181K (4)| 00:36:14 | | 4 | BITMAP CONVERSION TO ROWIDS | | 926K| 22M| | 2279 (1)| 00:00:28 | | 5 | BITMAP INDEX FAST FULL SCAN| I_M_LOG_MVIEW_4 | | | | | | |* 6 | TABLE ACCESS FULL | USERS | 15M| 1630M| | 86638 (6)| 00:17:20 | |* 7 | HASH JOIN | | 7646K| 1020M| 33M| 231K (4)| 00:46:13 | | 8 | BITMAP CONVERSION TO ROWIDS | | 926K| 22M| | 2279 (1)| 00:00:28 | | 9 | BITMAP INDEX FAST FULL SCAN| I_M_LOG_MVIEW_4 | | | | | | | 10 | TABLE ACCESS FULL | USERS | 23M| 2515M| | 87546 (7)| 00:17:31 | --------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("U"."NAME"="L"."USER_NAME") 6 - filter("U"."NAME" IS NOT NULL) 7 - access("U"."USER_ID"=TO_NUMBER("L"."USER_ID")) filter(LNNVL("U"."NAME"="L"."USER_NAME") OR LNNVL("U"."NAME" IS NOT NULL)) Note ----- - dynamic sampling used for this statement
Для тех, кто используетwhere exists
:
Plan hash value: 2786958565 ----------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 114 | 21M (1)| 70:12:13 | |* 1 | FILTER | | | | | | | 2 | TABLE ACCESS FULL | USERS | 23M| 2515M| 87681 (7)| 00:17:33 | | 3 | BITMAP CONVERSION TO ROWIDS | | 7062 | 179K| 1 (0)| 00:00:01 | |* 4 | BITMAP INDEX FAST FULL SCAN| I_M_LOG_MVIEW_4 | | | | | ----------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter( EXISTS (SELECT /*+ */ 0 FROM "MYSCHEMA"."LOG_MVIEW" "LOG_MVIEW" WHERE ("USER_NAME"=:B1 OR TO_NUMBER("USER_ID")=:B2) AND ("USER_NAME"=:B3 OR TO_NUMBER("USER_ID")=:B4) AND ("USER_NAME"=:B5 OR TO_NUMBER("USER_ID")=:B6))) 4 - filter("USER_NAME"=:B1 OR TO_NUMBER("USER_ID")=:B2) Note ----- - dynamic sampling used for this statement
Имена объектов БД изменены, чтобы защитить невинных. :п