Oracle SQL-连接比较空值的性能
早上好Oracle SQL-连接比较空值的性能,sql,performance,oracle,join,Sql,Performance,Oracle,Join,早上好 昨天我在两个大小合适的结果集之间编写了一个查询(第一种情况下为45分钟,而第二种情况下为,因为每个空值都不同,所以数据库不使用优化(对于a中的每一行,检查表b中的每一行) 在第二种情况下,数据库首先将所有空值更改为“N/A”,然后使用优化只比较A.class和b.class 在Oracle中比较空值非常耗时。空值是未定义的值-一个空值不同于另一个空值。 比较两个几乎相同的查询的结果: select 1 from dual where null is null select 1 from
昨天我在两个大小合适的结果集之间编写了一个查询(第一种情况下为45分钟,而第二种情况下为,因为每个空值都不同,所以数据库不使用优化(对于
a
中的每一行,检查表b
中的每一行)
在第二种情况下,数据库首先将所有空值更改为“N/A”,然后使用优化只比较A.class
和b.class
在Oracle中比较空值非常耗时。空值是未定义的值-一个空值不同于另一个空值。
比较两个几乎相同的查询的结果:
select 1 from dual where null is null
select 1 from dual where null = null
只有带有特殊的第一个查询是null
子句才能返回正确答案。因此,空值不能被索引。请尝试以下方法:
SELECT a from Table1 a JOIN JTable1 b ON a.class = b.class
where a.class is null
union all
SELECT a from Table1 a JOIN JTable1 b ON a.class = b.class
where b.class is null
应该快一点为什么不简单一点呢。 像 挑选* 从a到b 哪里 a、 类(+)=b.class(+)
我认为它更具可读性。您返回的是带有空类记录的叉积。这对您的结果合适吗 我在11gR2中创建了两个示例查询:
WITH a as
(select NULL as class, 5 as columna from dual
UNION
select NULL as class, 7 as columna from dual
UNION
select NULL as class, 9 as columna from dual
UNION
select 'X' as class, 3 as columna from dual
UNION
select 'Y' as class, 2 as columna from dual),
b as
(select NULL as class, 2 as columnb from dual
UNION
select NULL as class, 15 as columnb from dual
UNION
select NULL as class, 5 as columnb from dual
UNION
select 'X' as class, 7 as columnb from dual
UNION
select 'Y' as class, 9 as columnb from dual)
SELECT * from a JOIN b ON (a.class = b.class
OR (a.class is null AND b.class is null))
当我在这个查询上运行EXPLAIN PLAN时,它指示表(在我的例子中是内联视图)通过嵌套循环联接。嵌套循环联接的操作方式是扫描一个表的第一行,然后扫描另一个表的每一行以查找匹配项,然后扫描第一个表的第二行,在第二个表上查找匹配项,等等。因为您没有直接比较联接中的表或部分,所以优化器必须se嵌套循环
在幕后,它可能看起来像:
- 获取表A的第1行。如果类为null,则在结果集中包含表A中的此行
- 当仍在表A第1行时,在表B中搜索class为null的所有行
- 对表a第1行和表B中的所有行执行叉积
- 将这些行包括在结果集中
- 获取表A第2行。如果类为null,则将表A中的此行包含在结果集中
- ……等等
SELECT*时,从NVL上的联接b(a.class,'N/a')=NVL(b.class,'N/a'))
,EXPLAIN表示使用了散列联接。散列联接基本上生成较小表的每个联接键的散列,然后扫描较大表,在较小表中查找匹配的每一行的散列。在这种情况下,由于它是一个简单的等联接,优化器可以对驱动表的每一行进行散列,而不会出现问题
在幕后,它可能看起来像:
- 浏览表A,将空类值转换为“N/A”
- 边走边散列表A的每一行
- 哈希表A现在位于临时空间或内存中
- 扫描表B,将空类值转换为“N/A”,然后计算值的哈希值。哈希表中的查找哈希值(如果存在)包括结果集中表A和B中的联接行
- 继续扫描B
COALESCE
函数在其他数据库系统中模拟NVL oracle函数。这里的真正问题是,您正试图加入一个空值,在这个空值上,您确实应该有一个“无类”或其他方法来识别一个空=无而不是空=未知意义上的“空”类
在评论中回答您的问题的附录:
对于空查询,SQL引擎将执行以下操作:
SELECT a from Table1 a JOIN JTable1 b ON a.class = b.class
where a.class is null
union all
SELECT a from Table1 a JOIN JTable1 b ON a.class = b.class
where b.class is null
WITH a as
(select NULL as class, 5 as columna from dual
UNION
select NULL as class, 7 as columna from dual
UNION
select NULL as class, 9 as columna from dual
UNION
select 'X' as class, 3 as columna from dual
UNION
select 'Y' as class, 2 as columna from dual),
b as
(select NULL as class, 2 as columnb from dual
UNION
select NULL as class, 15 as columnb from dual
UNION
select NULL as class, 5 as columnb from dual
UNION
select 'X' as class, 7 as columnb from dual
UNION
select 'Y' as class, 9 as columnb from dual)
SELECT * from a JOIN b ON (a.class = b.class
OR (a.class is null AND b.class is null))