解释计划如何在应用程序之间产生差异

时间:2014-01-17 10:21:24

标签: sql oracle sql-execution-plan

我在这里公开了一个非常奇怪的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
) 

3 个答案:

答案 0 :(得分:2)

执行计划可能因优化程序目标以及平台/驱动程序中的异常(我认为是一个错误,但它已经存在很多)而有所不同。

请在会话中检查optimizer_goal的设置。

还要确保检查相同条件和相同数据。价值偷看可能导致不同的执行计划,以及不同的统计和平台。

  

另一个原因可能是Oracle内核默认为另一个   SQL和PL / SQL的首选optimizer_goal:使用PL / SQL all_rows和   我记得正确的时候默认使用SQL first_rows。

一些SQL提示:

  1. 不要在çabmnt___ rforefide ='TEST'周围使用();它们是多余的。
  2. 考虑分析函数,而不是依赖于内联视图中的订单。
  3. 在内联中排序是错误的编码风格(恕我直言)。
  4. 更好地将'1 = 1'移到'where'后面,这使得编辑更容易(但有时会导致优化问题)。把现在的东西放在'和'的里面。或者删除它。

答案 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视为我的好指数!!!