如何避免Oracle sql查询中的笛卡尔积?
我在Oracle中遇到以下查询的性能问题:如何避免Oracle sql查询中的笛卡尔积?,sql,oracle,Sql,Oracle,我在Oracle中遇到以下查询的性能问题: create table table2 as select t.tab_key, t.x, t.y, t.val , s.val val2, sqrt(power(t.x - s.x, 2) + power(t.y - s.y, 2)) d from table1 t join table1 s on s.val is not null and s.tab_key != t.tab_key and
create table table2 as
select t.tab_key, t.x, t.y, t.val , s.val val2, sqrt(power(t.x - s.x, 2) + power(t.y - s.y, 2)) d
from table1 t
join table1 s on s.val is not null and
s.tab_key != t.tab_key and
sqrt(power(t.x - s.x, 2) + power(t.y - s.y, 2)) <= 290;
将表2创建为
选择t.tab_键,t.x,t.y,t.val,s.val val2,sqrt(功率(t.x-s.x,2)+功率(t.y-s.y,2))d
来自表1 t
s.val上的联接表1不为null,并且
s、 tab_键!=t、 tab_键和
sqrt(幂(t.x-s.x,2)+幂(t.y-s.y,2))你不能避免笛卡尔积;但是,可以提供其他限制,以便在计算坐标之间的确切距离和执行连接之前,过滤掉坐标值之间的明显差异
您正在尝试查看一个坐标是否位于半径为290个单位的圆内。如果该值在该圆内,则该值也在该圆周围的边界框内;这可能允许您在x
和y
坐标上使用索引
您还可以通过对两边进行平方运算来摆脱连接中的(昂贵的)平方根运算;但是,这可能不是一个显著的节省,因为您仍将对匹配的行执行平方根运算
将表2创建为
选择t.tab_键,
t、 x,,
t、 y,,
t、 瓦尔,
s、 瓦尔瓦尔2号,
sqrt(功率(t.x-s.x,2)+功率(t.y-s.y,2))d
来自表1 t
加入表1和表2
on(s.val不为空
和s.tab_键!=t.tab_键
t.x在s.x-290和s.x+290之间
t.y在s.y-290和s.y+290之间
power(t.x-s.x,2)+power(t.y-s.y,2)您不能添加索引来改进查询,因为索引基于表,而索引必须基于两个表(相同,但不能这样做)
数据库必须从一个表开始,并检查第二个表中的每一行是否符合您的条件。我认为这不能用其他方式完成。这就像问一个问题:“请在靠近其他地方的每个地方找到我”-您必须检查所有组合。请提供示例数据、所需结果和查询逻辑的解释。无法避免笛卡尔积,因为您必须评估每一行组合。我唯一的建议是尝试其他类似databricks的方法,您可以通过c完成后,alcs将其关闭。@Nick.McDermaid是否有办法施加条件sqrt(功率(t.x-s.x,2)+功率(t.y-s.y,2))@Nick.McDermaid没有办法避免笛卡尔连接,但您可以限制连接考虑的行明显将超出您正在筛选的圆半径,以便笛卡尔连接仅在表的子集上执行,而不考虑每行的整个表。作为替代方法u可以将X、Y值作为点几何体存储在Oracle sdo_几何体列中。创建空间索引并使用sdo_in_distance获取指定距离内的所有点。谢谢,我会尝试。为什么要在4列tab_key、val、X、Y上创建索引,而不是在两列X、Y上创建索引,或者在X和Y上分别创建两个索引?4列允许您仅使用索引;但是,仅在x any y y上使用索引也可以给您带来好处-使用x
和y
列上的index RANGE SCAN
显示它,以限制它需要加入的行。关于使用不太密集的谓词进行预筛选的出色观察。
| PLAN_TABLE_OUTPUT |
| :------------------------------------------------------------------------------------------ |
| Plan hash value: 2623360073 |
| |
| ------------------------------------------------------------------------------------------- |
| | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | |
| ------------------------------------------------------------------------------------------- |
| | 0 | SELECT STATEMENT | | 1 | 104 | 4 (50)| 00:00:01 | |
| | 1 | MERGE JOIN | | 1 | 104 | 4 (50)| 00:00:01 | |
| | 2 | SORT JOIN | | 5 | 260 | 2 (50)| 00:00:01 | |
| | 3 | INDEX FULL SCAN | TABLE1__TK_V_X_Y_IDX | 5 | 260 | 1 (0)| 00:00:01 | |
| |* 4 | FILTER | | | | | | |
| |* 5 | SORT JOIN | | 5 | 260 | 2 (50)| 00:00:01 | |
| |* 6 | INDEX FULL SCAN| TABLE1__TK_V_X_Y_IDX | 5 | 260 | 1 (0)| 00:00:01 | |
| ------------------------------------------------------------------------------------------- |
| |
| Predicate Information (identified by operation id): |
| --------------------------------------------------- |
| |
| 4 - filter("S"."TAB_KEY"<>"T"."TAB_KEY" AND "T"."X"<="S"."X"+290 AND |
| "T"."Y">="S"."Y"-290 AND "T"."Y"<="S"."Y"+290 AND |
| POWER("T"."X"-"S"."X",2)+POWER("T"."Y"-"S"."Y",2)<=84100) |
| 5 - access(INTERNAL_FUNCTION("T"."X")>="S"."X"-290) |
| filter(INTERNAL_FUNCTION("T"."X")>="S"."X"-290) |
| 6 - filter("S"."VAL" IS NOT NULL) |
| |
| Note |
| ----- |
| - dynamic sampling used for this statement (level=2) |
| PLAN_TABLE_OUTPUT |
| :--------------------------------------------------------------------------------------------- |
| Plan hash value: 806357607 |
| |
| ---------------------------------------------------------------------------------------------- |
| | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | |
| ---------------------------------------------------------------------------------------------- |
| | 0 | SELECT STATEMENT | | 1 | 104 | 4 (0)| 00:00:01 | |
| | 1 | NESTED LOOPS | | 1 | 104 | 4 (0)| 00:00:01 | |
| | 2 | INDEX FULL SCAN | TABLE1__TK_V_X_Y_IDX | 5 | 260 | 1 (0)| 00:00:01 | |
| |* 3 | INDEX FAST FULL SCAN| TABLE1__TK_V_X_Y_IDX | 1 | 52 | 1 (0)| 00:00:01 | |
| ---------------------------------------------------------------------------------------------- |
| |
| Predicate Information (identified by operation id): |
| --------------------------------------------------- |
| |
| 3 - filter("S"."VAL" IS NOT NULL AND "S"."TAB_KEY"<>"T"."TAB_KEY" AND |
| POWER("T"."X"-"S"."X",2)+POWER("T"."Y"-"S"."Y",2)<=84100) |
| |
| Note |
| ----- |
| - dynamic sampling used for this statement (level=2) |