使用'<'进行INNER JOIN表演或'>'条件

时间:2016-12-21 17:56:45

标签: sql oracle indexing inner-join

我有两个表SessionOrder的表。此列是整数数据类型,并具有以下索引:CREATE INDEX OSIDX_<internal name> ON <Entity>

我正在执行以下查询:

SELECT i_0.rn, i_1.rn 
FROM (
    SELECT "RawEvent"."SessionOrder" as rn
    FROM "RawEvent" i_0
    WHERE something = 12
)
INNER JOIN (
    SELECT "RawEvent"."SessionOrder" as rn
    FROM "RawEvent" i_1
    WHERE something = 14
) ON i_0.rn > i_1.rn

此查询的问题是ON i_0.rn > i_1.rn变得太慢而且超时。 我将其替换为ON i_0.rn = i_1.rn并且它非常快,但显然不会产生预期的结果。

是否有人知道如何提高此查询的性能以避免超时? 此问题的其他目标是了解为什么ON i_0.rn > i_1.rn会导致性能下降。

PS:无法增加超时时间

3 个答案:

答案 0 :(得分:3)

如果您真的使用Oracle数据库,请先检查。 SQL的语法建议使用其他RDBMS或某些预处理器。

要获得您对此类查询的期望,您可以使用如下虚拟示例。

生成样本数据

create table myTab as 
with mySeq as 
(select rownum SessionOrder from dual connect by level <= 10000)
select 12 something, SessionOrder from mySeq union all
select 14  something, SessionOrder from mySeq
;

这产生两个子源,每个子源具有从1到10.000开始的10.000个序列。

测试查询

create table myRes as
select a.SessionOrder rn0, b.SessionOrder rn1
from myTab a join myTab b on a.SessionOrder > b.SessionOrder and
a.something = 12 and b.something = 14;

在不到30秒的时间内产生49.995.000行。

如果您希望在更短的时间内获得如此大的结果,那么您需要进行高级优化。在不知道您的数据和要求的情况下,不可能提供一般的建议。

答案 1 :(得分:1)

根据建议,我尝试用其他策略来解决问题,从而获得更高的性能。

尽管有这个简单的解决方案,但我不明白为什么原始查询太慢了。我认为Oracle引擎没有使用索引。

SELECT i_0."SessionOrder",  i_1."SessionOrder"
FROM "RawEvent" i_0
INNER JOIN "RawEvent" i_1 ON  i_0."SessionOrder" < i_1."SessionOrder" 
WHERE i_0."something" = 12 AND i_1."something" = 14

答案 2 :(得分:0)

您的查询执行三项任务:

1)获取两个子集(12和14)的数据

2)加入数据和

3)将结果传递给客户

请注意,索引访问(您怀疑会导致问题)仅与步骤1相关。 因此,为了获得更好的印象,首先要实现三个步骤之间经过的时间分布。 这可以使用SQL * Plus完成(我使用与之前答案相同的生成数据)

数据访问

由于我的表没有索引,执行count(*)会执行FULL TABLE SCAN。因此,在最坏的情况下,使用两倍的时间来获取数据。

SQL> set timi on
SQL> set autotrace on
SQL> select count(*) from mytab;

  COUNT(*)
----------
     20000

Elapsed: 00:00:01.13

Execution Plan
----------------------------------------------------------
Plan hash value: 3284627250

--------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Cost (%CPU)| Time     |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |  5472   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE    |       |     1 |            |          |
|   2 |   TABLE ACCESS FULL| MYTAB | 20000 |  5472   (1)| 00:00:01 |
--------------------------------------------------------------------

FTS已准备好大约一秒钟,所以要让两个组都成为aprox。两秒钟过去了。

<强> JOIN

可以使用连接查询的CTAS模拟连接所用的时间。

SQL> create table myRes as
  2  select a.SessionOrder rn0, b.SessionOrder rn1
  3  from myTab a join myTab b on a.SessionOrder > b.SessionOrder and
  4  a.something = 12 and b.something = 14;

Table created.

Elapsed: 00:00:23.65

Join返回近50M行(由于大于条件)并花费大约21秒(我为数据访问减去2秒)。

将数据传递给客户

我们使用选项set autotrace traceonly来抑制客户端屏幕上的查询输出,但数据已传输,因此我们可以 衡量时间。 (如果在屏幕上渲染结果,时间会更高)

SQL> SET ARRAYSIZE 5000
SQL> set autotrace traceonly
SQL> select a.SessionOrder rn0, b.SessionOrder rn1
  2  from myTab a join myTab b on a.SessionOrder > b.SessionOrder and
  3  a.something = 12 and b.something = 14;

49995000 rows selected.

Elapsed: 00:03:03.89

Execution Plan
----------------------------------------------------------
Plan hash value: 2857240533

-----------------------------------------------------------------------------
| Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |       |    49M|   667M| 11077   (2)| 00:00:01 |
|   1 |  MERGE JOIN         |       |    49M|   667M| 11077   (2)| 00:00:01 |
|   2 |   SORT JOIN         |       | 10000 | 70000 |  5473   (1)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL| MYTAB | 10000 | 70000 |  5472   (1)| 00:00:01 |
|*  4 |   SORT JOIN         |       | 10000 | 70000 |  5473   (1)| 00:00:01 |
|*  5 |    TABLE ACCESS FULL| MYTAB | 10000 | 70000 |  5472   (1)| 00:00:01 |
-----------------------------------------------------------------------------

这是花费大约2:40分钟的时间

<强>摘要

因此,在总共3分钟的场景中,仅花费大约2秒钟来进行数据访问(或大约1%)。 即使您将数据访问权限削减到十分之一 - 您几乎看不到任何差异。 问题在于连接,甚至更多的是将数据传输到客户端。

索引可以帮助

当然这取决于......

在一个非常特殊的情况下,你有一个非常大的表,只有很少的数据something in (12,14) 您可以从 AND SessionOrder上定义的索引中获利。这允许使用仅索引访问数据,完全绕过表访问。