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
答案 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;