如何避免Oracle sql查询中的笛卡尔积?

如何避免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

我在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
                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) |