SQL语句奇怪的慢

时间:2011-02-14 11:56:16

标签: sql performance oracle optimization

select TABLE1.FIELD1, 
       TABLE1.FIELD2, 
       TABLE1.FIELD3, 
       TABLE1.FIELD4, 
       TABLE1.FIELD5, 
       TABLE2.FIELD6, 
       TABLE2.FIELD7
  from TABLE1,
       TABLE2
 where TABLE1.FIELD8 = 'value' 
   and TABLE2.FIELD6 = TABLE1.FIELD6;

我正在搜索来自2个不同表格的一些数据。 (Oracle数据库 - wherefields为两个表编制索引) 上述查询需要500ms才能执行。 当我单独搜索表格中的相同字段时 他们每人不到20毫秒完成。

我可以在TABLE1中搜索我需要的数据(+ FIELD6) 然后使用FIELD6搜索TABLE2以获取其余部分。

我的问题是。当我加入桌子时为什么这么慢? 我做错了吗?

编辑:添加oracle的解释计划

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
| Id  | Operation                    |  Name                   | Rows  | Bytes | Cost  |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                         |  6318 |   586K|   620 |
|   1 |  HASH JOIN                   |                         |  6318 |   586K|   620 |
|   2 |   TABLE ACCESS BY INDEX ROWID| TABLE1                  |  6318 |   450K|     2 |
|   3 |    INDEX RANGE SCAN          | INDEX_TABLE1_FIELD8     |  2527 |       |     1 |
|   4 |   TABLE ACCESS FULL          | TABLE2                  |   430K|  9242K|   508 |
----------------------------------------------------------------------------------------

Note: cpu costing is off, 'PLAN_TABLE' is old version

5 个答案:

答案 0 :(得分:2)

如果TABLE1中有25条记录满足field8='value',如果它需要20ms到select ... from table2 where field6=???,那么500ms就在预期时间范围内。

因此,说每个查询花费20ms是非常有意义的,你还必须说明有多少记录满足TABLE1中的field8条件以及平均有多少记录满足TABLE2.FIELD6上的条件。

但要消除所有猜测,您应该让Oracle解释查询并在此处显示(或发布)解释的计划以供进一步分析。

编辑:由于标准之间似乎存在1:1关系(并且查询随后返回1条记录),因此不期望500毫秒。在这种情况下,我真的强调需要解释查询。如果你不熟悉它,你可以这样做:

explain plan for
   select .... <your entire select statement goes here>
;

select * from table(dbms_xplan.display);

然后发布结果。这将使我们能够更好地帮助您。

答案 1 :(得分:2)

比什么慢? RDBMS是为加入而制作的。如果你认为从程序上做这个(逐行使用游标循环或类似的)你会得到更好的响应时间,那么99.9%的时间你就错了。

我的猜测是你要比较一个返回所有行的连接的响应时间(如果使用FIRST_ROWS,甚至是前500行左右)与一些程序(或手动)返回的记录。苹果和橘子。

答案 2 :(得分:1)

您应该知道查询计划是什么,使用报告工具或/*+ gather_plan_statistics */等提示。在搜索引擎上查找此信息。

当优化器连接两个表时,它可以使用笛卡尔积,排序合并连接,散列连接......尝试SELECT /*+ USE_HASH(table1 table2) */ …

此外,如果优化程序选择了错误的计划,您可能希望使用DBMS_STATS.GATHER_SCHEMA_STATS过程重新计算统计数据(如果它们不具代表性)。这是糟糕的优化器选择的主要来源。

答案 3 :(得分:1)

我看不出您的查询有任何问题,其他答案中提供的(好)建议将帮助您了解详细情况。

但是,在概念上,您必须牢记每个表中数据的顺序,以及数据是分组还是分散。一切都很好说“它只需要20ms才能找到”,但匹配两个数据集需要多长时间?

如果两个数据集的已知顺序相同,则RDBMS可以相对快速地对齐它们。但是RDBMS只能从索引中知道这一点。

如果Table1上的索引是Field8然后是Field6,则所有“值”将被集中在一起,然后由Field6排序。但是,如果您有Field6的索引然后是Field8,那么您感兴趣的记录将被排序但通过索引展开。最后,如果您没有这些字段的索引,则所有内容都将随机排序并展开。

根据这些类型的因素,RDBMS可以通过几十种方式完成查询。为了获得最佳性能,需要了解RDBMS需要做什么,然后给它索引以使其尽可能简单。

答案 4 :(得分:1)

您应该分析这些表...在您的情况下,完整的表访问和散列连接是没有意义的。

begin
  dbms_stats.gather_table_stats('YOURUSERNAME', 'TABLE1');
  dbms_stats.gather_table_stats('YOURUSERNAME', 'TABLE2');
end;