我在这里公开了一个非常奇怪的Oracle 11g请求行为。
这里是请求:
SELECT *
FROM (SELECT *
FROM (SELECT cabmnt___rfovsnide AS c0
FROM cabmnt
WHERE cabmnt___rfovsnide > '200912_001'
AND 1 = 1
AND ( cabmnt___rforefide = 'TEST' )
AND cabmnt___rfovsnide IS NOT NULL
ORDER BY c0)
WHERE rownum = 1);
我的列cabmnt___rfovsnide上有一个索引。
问题在于:
在SQLPLUS上:它使用一个很好的计划,索引扫描
在SQUIRRELSQL上:它使用相同的好计划,索引扫描
在SQLDEVELLOPER上:它使用了一个带有TABLE FULL SCAN的邪恶计划(100M行:()
在EntrepriseManager上:它使用了一个带有TABLE FULL SCAN的邪恶计划(100M行:()
在我的真实APP中:它使用了一个带有TABLE FULL SCAN的邪恶计划(100M行:()
有了好的计划,查询需要0.001秒。
坏的:超过2分钟。
你有什么想法吗?
请求信息:
CURSOR_SHARING是完全的。
我在同一个数据库上播放所有这些测试
好计划:(在SQLPLUS和SQuiRREL
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 4 (100)| |
| 1 | VIEW | | 1 | 18 | 4 (0)| 00:00:01 |
|* 2 | COUNT STOPKEY | | | | | |
| 3 | VIEW | | 2 | 36 | 4 (0)| 00:00:01 |
|* 4 | TABLE ACCESS BY INDEX ROWID| CABMNT | 2 | 36 | 4 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | CABMNT_VSN | | | 3 (0)| 00:00:01 |
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM=1)
4 - filter("CABMNT___RFOREFIDE"='TEST')
5 - access("CABMNT___RFOVSNIDE">'200912_001')
所有行的糟糕计划:(在SQLDEVELLOPER,企业管理器和我的APP
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | | 140K(100)| |
| 1 | VIEW | | 1 | 18 | | 140K (1)| 00:32:43 |
|* 2 | COUNT STOPKEY | | | | | | |
| 3 | VIEW | | 16M| 288M| | 140K (1)| 00:32:43 |
|* 4 | SORT ORDER BY STOPKEY| | 16M| 288M| 450M| 140K (1)| 00:32:43 |
|* 5 | TABLE ACCESS FULL | CABMNT | 16M| 288M| | 79979 (1)| 00:18:40 |
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM=1)
4 - filter(ROWNUM=1)
5 - filter(("CABMNT___RFOVSNIDE">'200912_001' AND "CABMNT___RFOREFIDE"='TEST'))
有第一行的坏计划:(在SQLDEVELLOPER,企业管理者和我的APP
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | | 360K(100)| |
| 1 | VIEW | | 1 | 18 | | 360K (1)| 01:24:13 |
|* 2 | COUNT STOPKEY | | | | | | |
| 3 | VIEW | | 16M| 288M| | 360K (1)| 01:24:13 |
|* 4 | SORT ORDER BY STOPKEY | | 16M| 288M| 450M| 360K (1)| 01:24:13 |
|* 5 | TABLE ACCESS BY INDEX ROWID| CABMNT | 16M| 288M| | 300K (1)| 01:10:10 |
|* 6 | INDEX RANGE SCAN | CABMNT_VSN | 16M| | | 29139 (1)| 00:06:48 |
------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM=1)
4 - filter(ROWNUM=1)
5 - filter("CABMNT___RFOREFIDE"='TEST')
6 - access("CABMNT___RFOVSNIDE">'200912_001')
我的专栏索引:
CREATE INDEX "AXABAS"."CABMNT_VSN" ON "AXABAS"."CABMNT" ("CABMNT___RFOVSNIDE")
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE
DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "TB_STRUCTURES_AXABAS_OLD"
null
我创建它只是:
CREATE INDEX cabmnt_vsn on cabmnt (cabmnt___rfovsnide);
表DDL
CREATE TABLE cabmnt
(
**cabmnt___rforefide varchar(32) NOT NULL, -- Referentiel**
cabmnt___rteprcide varchar(32) NOT NULL,
cabmnt___rtestdide varchar(32) NOT NULL, -- Stade
**cabmnt___rfovsnide varchar(32) NOT NULL, -- Version**
cabmntlil varchar(100), -- libelle long
cabmntlic varchar(32), -- libelle court
cabmnttxt varchar(1500), -- Commentaires
cabmnt___rfontride varchar(32) NOT NULL, -- Nature
cabmnt_1_rfodstide varchar(32), -- Destination axe 1
cabmnt_2_rfodstide varchar(32), -- Destination axe 2
cabmnt_3_rfodstide varchar(32), -- Destination axe 3
cabmnt_4_rfodstide varchar(32), -- Destination axe 4
cabmnt_5_rfodstide varchar(32), -- Destination axe 5
cabmnt_6_rfodstide varchar(32), -- Destination axe 6
cabmnt_7_rfodstide varchar(32), -- Destination axe 7
cabmnt_8_rfodstide varchar(32), -- Destination axe 8
cabmnt_9_rfodstide varchar(32), -- Destination axe 9
cabmntmnt numeric(25,10) NOT NULL, -- Montant
cabmntsns varchar(1), -- Sens
cabmnt___rfodevide varchar(32), -- Devise
cabmnt___rfotytide varchar(32), -- Type de taux devise
cabmntdtc timestamp, -- Date du taux
cabmntmtd numeric(25,10), -- Montant en devise
cabmnt___rfocteide varchar(32), -- cycle temporel
cabmntdtd timestamp NOT NULL, -- Date debut
cabmntdtf timestamp NOT NULL, -- Date fin
cabmntcsu integer NOT NULL, -- Cle de substitution
cabmntax1 integer DEFAULT 1 NOT NULL,
cabmntax2 integer DEFAULT 2 NOT NULL,
cabmntax3 integer DEFAULT 3 NOT NULL,
cabmntax4 integer DEFAULT 4 NOT NULL,
cabmntax5 integer DEFAULT 5 NOT NULL,
cabmntax6 integer DEFAULT 6 NOT NULL,
cabmntax7 integer DEFAULT 7 NOT NULL,
cabmntax8 integer DEFAULT 8 NOT NULL,
cabmntax9 integer DEFAULT 9 NOT NULL,
cabmnt_o_cabmntcsu integer, -- Montant d'origine
cabmnt___cabodvcsu integer, -- OD analytique
cabmnt___cabliscsu integer, -- Lissage
**CONSTRAINT cabmnt_pk PRIMARY KEY (cabmntcsu) USING INDEX TABLESPACE tb_index_axabas,**
CONSTRAINT cabmnt_fk_dev FOREIGN KEY (cabmnt___rforefide, cabmnt___rfodevide)
REFERENCES rfodev (rfodev___rforefide, rfodevide) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ds1 FOREIGN KEY (cabmnt___rforefide, cabmnt_1_rfodstide, cabmntax1)
REFERENCES rfodst (rfodst___rforefide, rfodstide, rfodstaxe) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ds2 FOREIGN KEY (cabmnt___rforefide, cabmnt_2_rfodstide, cabmntax2)
REFERENCES rfodst (rfodst___rforefide, rfodstide, rfodstaxe) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ds3 FOREIGN KEY (cabmnt___rforefide, cabmnt_3_rfodstide, cabmntax3)
REFERENCES rfodst (rfodst___rforefide, rfodstide, rfodstaxe) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ds4 FOREIGN KEY (cabmnt___rforefide, cabmnt_4_rfodstide, cabmntax4)
REFERENCES rfodst (rfodst___rforefide, rfodstide, rfodstaxe) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ds5 FOREIGN KEY (cabmnt___rforefide, cabmnt_5_rfodstide, cabmntax5)
REFERENCES rfodst (rfodst___rforefide, rfodstide, rfodstaxe) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ds6 FOREIGN KEY (cabmnt___rforefide, cabmnt_6_rfodstide, cabmntax6)
REFERENCES rfodst (rfodst___rforefide, rfodstide, rfodstaxe) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ds7 FOREIGN KEY (cabmnt___rforefide, cabmnt_7_rfodstide, cabmntax7)
REFERENCES rfodst (rfodst___rforefide, rfodstide, rfodstaxe) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ds8 FOREIGN KEY (cabmnt___rforefide, cabmnt_8_rfodstide, cabmntax8)
REFERENCES rfodst (rfodst___rforefide, rfodstide, rfodstaxe) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ds9 FOREIGN KEY (cabmnt___rforefide, cabmnt_9_rfodstide, cabmntax9)
REFERENCES rfodst (rfodst___rforefide, rfodstide, rfodstaxe) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ntr FOREIGN KEY (cabmnt___rforefide, cabmnt___rfontride)
REFERENCES rfontr (rfontr___rforefide, rfontride) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_ref FOREIGN KEY (cabmnt___rforefide)
REFERENCES rforef (rforefide) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_std FOREIGN KEY (cabmnt___rteprcide, cabmnt___rtestdide)
REFERENCES rtestd (rtestd___rteprcide, rtestdide) --MATCH SIMPLE
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
**CONSTRAINT cabmnt_fk_vsn FOREIGN KEY (cabmnt___rforefide, cabmnt___rfovsnide)
REFERENCES rfovsn (rfovsn___rforefide, rfovsnide) --MATCH SIMPLE**
,----ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT cabmnt_fk_tyt FOREIGN KEY (cabmnt___rforefide, cabmnt___rfotytide)
REFERENCES rfotyt (rfotyt___rforefide, rfotytide),
CONSTRAINT cabmnt_fk_cte FOREIGN KEY (cabmnt___rforefide, cabmnt___rfocteide)
REFERENCES rfocte (rfocte___rforefide, rfocteide) DEFERRABLE,
CONSTRAINT cabmnt_fk_vct FOREIGN KEY (cabmnt___rforefide, cabmnt___rfovsnide, cabmnt___rfocteide)
REFERENCES rfovsn (rfovsn___rforefide, rfovsnide, rfovsn___rfocteide) DEFERRABLE,
CONSTRAINT cabmnt_fk_per FOREIGN KEY (cabmnt___rforefide, cabmnt___rfocteide, cabmntdtd)
REFERENCES rfoper (rfoper___rforefide, rfoper___rfocteide, rfoperdtd) DEFERRABLE
)
答案 0 :(得分:2)
执行计划可能因优化程序目标以及平台/驱动程序中的异常(我认为是一个错误,但它已经存在很多)而有所不同。
请在会话中检查optimizer_goal的设置。
还要确保检查相同条件和相同数据。价值偷看可能导致不同的执行计划,以及不同的统计和平台。
另一个原因可能是Oracle内核默认为另一个 SQL和PL / SQL的首选optimizer_goal:使用PL / SQL all_rows和 我记得正确的时候默认使用SQL first_rows。
一些SQL提示:
答案 1 :(得分:1)
您是否尝试过以下操作?:
SELECT max(cabmnt___rfovsnide) AS c0
FROM cabmnt
WHERE cabmnt___rfovsnide > '200912_001'
AND cabmnt___rforefide = 'TEST'
AND cabmnt___rfovsnide IS NOT NULL ;
答案 2 :(得分:0)
我尝试自动回答:)
我的最终目标是在cabmnt中请求rfovsnide的所有不同值,我发现的最佳方法是播放我向您呈现的查询,因为它可以找到另一个版本(每次更改>条件),但是oracle决定不接受索引并且非常懒散
我发现另一个查询给出了相同的结果,并在每个场景中都采用了我的索引:
select rfovsnide from rfovsn
where rfovsn___rforefide = 'TEST'
and exists(
select 1 from cabmnt where cabmnt___rfovsnide = rfovsnide)
我颠倒了逻辑,把过滤器放在较轻的桌子上,只在我超大的桌子上检查id,计划很完美......两张桌子上的索引,即时查询......
修改强>
这是另一种选择,但并不是对真正问题的真正回应:为什么不要将ORACLE视为我的好指数!!!