我正在尝试创建表的子集(作为物化视图),定义为在另一个物化视图中具有匹配记录的那些记录。
例如,假设我有一个带有user_id和name列的Users表,以及一个带有entry_id,user_id,activity和timestamp列的Log表。
首先,我创建Log表的物化视图,仅选择时间戳>的那些行。 some_date。现在我想要在Log表的快照中引用的用户的母版化视图。我可以将其创建为
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
(需要使用distinct来避免来自具有多个日志条目的用户的多次点击)。
前者看起来更干净,更优雅,但需要更长时间。我错过了什么吗?有更好的方法吗?
编辑:where exists
子句有很多帮助,除非条件使用OR
。例如,假设上面的Log表也有一个user_name列,并且将Log条目与Users记录匹配的正确方法是列中的任何一列(用户ID或用户名)匹配。我找到了
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)
任何帮助?
(关于解释计划...... Lemme正在对它进行消毒,或者他们,而不是......我会在一段时间后发布它们。)
编辑:解释计划: 对于内部联接的查询:
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
更改了DB对象名称以保护无辜者。 :P
答案 0 :(得分:1)
这取决于您拥有的数据,但在联接中使用Distinct
可以提高您的效果:
Select u.*
From Users u
Join ( Select Distinct user_id
From log_mview ) l On u.user_id = l.user_id
答案 1 :(得分:1)
试试这个
select * from Users u
where exists
( select user_id
from Log_mview l
where l.user_id = u.user_id )
/
如果子查询返回大量行WHERE EXISTS
,则可能比WHERE ... IN
快得多。
答案 2 :(得分:1)
第二个查询可能比第一个查询(join + distinc)更多地使用硬盘驱动器。
第一个查询可能会转换为:
对于表中的每一行,日志在表User中找到相应的行(在内存中)。数据库可能足够聪明,可以在用户表的内存结构中创建,这可能比Log表小得多。
我相信查询一个(join + distinct)只需要在表Log上传递一个。
distinct可能是在内存中执行的。
第二个查询可能会强制数据库对表Log执行多次读取。
所以在第二个查询中你可能得到:
对于表中的每一行,用户读取表Log(来自磁盘)中的所有行以匹配条件。
您还必须考虑由于内存可用性,负载和表增加的变化,某些查询可能会遇到速度上的显着差异。