Oracle正在执行完全表扫描
我有一个连接两个表ISITEMFULL和Transaction的查询(它实际上搜索ISITEMFULL表中发票日期不为空的所有交易,而发票日期仅在事务表中定义)Oracle正在执行完全表扫描,oracle,performance,Oracle,Performance,我有一个连接两个表ISITEMFULL和Transaction的查询(它实际上搜索ISITEMFULL表中发票日期不为空的所有交易,而发票日期仅在事务表中定义) SELECT MIN(T.TRANSACTION) TRANSACTION , ISIL.ITEMID ITEM_NUMBER, ISIL.ITEMCOVER POLICY_NUMBER FROM TRANSACTION T,ISITEMFULL ISIL WHERE ISIL.SENT_FLG='T' AND T.TRANSAC
SELECT MIN(T.TRANSACTION) TRANSACTION ,
ISIL.ITEMID ITEM_NUMBER,
ISIL.ITEMCOVER POLICY_NUMBER
FROM TRANSACTION T,ISITEMFULL ISIL
WHERE ISIL.SENT_FLG='T'
AND T.TRANSACTION=ISIL.TRANSACTION
AND T.INVOICE_DAT IS NOT NULL
GROUP BY ISIL.ITEMID,ISIL.ITEMCOVER;
现在,ISITEMFULL的大小相对比事务表小(300万条记录),事务表有数十亿条记录。但是如果我查找plan,它会对事务表进行完全扫描。因此,查询需要花费大量时间。该计划如下所示:
SELECT STATEMENT, GOAL = CHOOSE Cost=2653711 Cardinality=1293564 Bytes=47861868
HASH GROUP BY Cost=2653711 Cardinality=1293564 Bytes=47861868
HASH JOIN Cost=2632362 Cardinality=1293564 Bytes=47861868
TABLE ACCESS FULL Object owner=PIE Object name=ISITEMFULL Cost=26845 Cardinality=1293564 Bytes=28458408
TABLE ACCESS FULL Object owner=PIE Object name=TRANSACTION Cost=2312319 Cardinality=201443101 Bytes=3021646515
--ISILMFULFILI4 - Transaction (in ISITEMFULL table)
--ISILMFULFILI7 - ITEMID (in ISITEMFULL table)
--ISILMFULFILI2 - ITEMCOVER (in ISITEMFULL table)
--TRANSACTIONP1- TRANSACTION (in TRANSACTION table)
--TRANSACTIONI10 - INVOICE_DAT (in TRANSACTION table).
尽管所有列都有各自的索引,但使用这些索引,而是以完整模式扫描事务表。
各列上定义的索引如下:
SELECT STATEMENT, GOAL = CHOOSE Cost=2653711 Cardinality=1293564 Bytes=47861868
HASH GROUP BY Cost=2653711 Cardinality=1293564 Bytes=47861868
HASH JOIN Cost=2632362 Cardinality=1293564 Bytes=47861868
TABLE ACCESS FULL Object owner=PIE Object name=ISITEMFULL Cost=26845 Cardinality=1293564 Bytes=28458408
TABLE ACCESS FULL Object owner=PIE Object name=TRANSACTION Cost=2312319 Cardinality=201443101 Bytes=3021646515
--ISILMFULFILI4 - Transaction (in ISITEMFULL table)
--ISILMFULFILI7 - ITEMID (in ISITEMFULL table)
--ISILMFULFILI2 - ITEMCOVER (in ISITEMFULL table)
--TRANSACTIONP1- TRANSACTION (in TRANSACTION table)
--TRANSACTIONI10 - INVOICE_DAT (in TRANSACTION table).
我曾尝试对这些索引使用提示,但几乎没有帮助。是否有其他方法可以停止对事务表的完全扫描,甚至查询
Select transaction from transaction TR where transaction in
(
Select transaction from isclmfulfil IC WHERE sent_FLG='T') and invoice_dat is not null;
要花很多时间
是否有任何方法可以告诉Oracle以更好的方式执行。
此外,表格上的统计数据是最新的。您是否尝试过这种变体:
SELECT MIN(ISIL.TRANSACTION),
ISIL.ITEMID ITEM_NUMBER,
ISIL.ITEMCOVER POLICY_NUMBER
FROM ISITEMFULL ISIL
WHERE ISIL.SENT_FLG='T'
AND EXISTS(SELECT /*+ index(t TRANSACTIONP1) */ *
FROM TRANSACTION T
WHERE T.TRANSACTION=ISIL.TRANSACTION
AND T.INVOICE_DAT IS NOT NULL)
GROUP BY ISIL.ITEMID,ISIL.ITEMCOVER;
?但无论如何,事务表中的129万个索引探测将需要一段时间。
(因此优化器选择完全扫描可能是正确的)。
您也可以尝试并行执行:
SELECT /*+ parallel(T, 4) */
MIN(T.TRANSACTION) TRANSACTION ,
ISIL.ITEMID ITEM_NUMBER,
ISIL.ITEMCOVER POLICY_NUMBER
FROM TRANSACTION T,ISITEMFULL ISIL
WHERE ISIL.SENT_FLG='T'
AND T.TRANSACTION=ISIL.TRANSACTION
AND T.INVOICE_DAT IS NOT NULL
GROUP BY ISIL.ITEMID,ISIL.ITEMCOVER;
您可以尝试不同程度的并行,以检查哪一个执行得更快。在散列连接之前,您可以尝试这些提示来扫描TRANSACTIONI10的范围
SELECT /*+ first_rows ordered use_hash(ISIL T) index(T TRANSACTIONI10) */
MIN(T.TRANSACTION) TRANSACTION ,
ISIL.ITEMID ITEM_NUMBER,
ISIL.ITEMCOVER POLICY_NUMBER
FROM ISITEMFULL ISIL, TRANSACTION T
WHERE ISIL.SENT_FLG='T'
AND T.TRANSACTION=ISIL.TRANSACTION
AND T.INVOICE_DAT IS NOT NULL
GROUP BY ISIL.ITEMID,ISIL.ITEMCOVER;
但探测事务表2.01亿次也需要大量时间。如果对这些查询进行SQL*跟踪,您将获得关于每个步骤执行时间的更多信息。
例如,您的SQL可能会花费大量时间,这不仅是因为完全扫描,还因为哈希工作区内存不足(在这种情况下,Oracle会将数据写入临时表空间,从而显著降低执行速度)。这也可以在V$SQL\u workarea\u ACTIVE view中进行检查(如果NUMBER_PASSES=0,则一切正常,1-缓慢,但或多或少可以接受,如果超过1,则构建哈希表可能需要太多时间)
(以防万一,如果您使用Exadata,由于卸载和存储索引,完全扫描将比大索引范围扫描更有效)
我还建议在
事务上创建函数索引(nvl2(发票数据,事务,空))
它将比组合索引更紧凑,因为它只存储事务
列,只存储不为空的发票数据
行,所以扫描速度更快。您需要修改查询以使用它:
SELECT MIN(ISIL.TRANSACTION) TRANSACTION ,
ISIL.ITEMID ITEM_NUMBER,
ISIL.ITEMCOVER POLICY_NUMBER
FROM TRANSACTION T,ISITEMFULL ISIL
WHERE ISIL.SENT_FLG='T'
AND ISIL.TRANSACTION = nvl2(INVOICE_DAT,TRANSACTION, NULL)
GROUP BY ISIL.ITEMID,ISIL.ITEMCOVER;
(在这种情况下,应省略对事务表的读取)创建多列索引:
在事务上创建索引somename(发票数据,事务)
Hi,谢谢你的评论。但是我不能创建索引,因为这是一个遗留的生产数据库,我只能使用可用的索引。有没有什么方法可以在使用索引后对两个表进行哈希连接(据我所知,索引是由嵌套循环使用的,而不是哈希)