Performance 我的Oracle查询在非常短和非常长的执行时间之间变化。什么会导致这一点?

Performance 我的Oracle查询在非常短和非常长的执行时间之间变化。什么会导致这一点?,performance,oracle,Performance,Oracle,[如果我重复发布此消息,我表示歉意-我以为我上周五发布了一个问题,但我的帐户没有显示任何问题。] 主要问题是:Linux上的Oracle11g在4秒到1.000秒的时间内完成并返回一个特定查询的数据。Oracle在两个不同的执行计划之间来回切换,其中一个执行计划的速度非常缓慢 我们已经确定了对查询的几个语义相同的更改,这使得Oracle不断选择快速执行计划。我们担心由于无明显原因的来回切换而出现错误或数据损坏 任何关于这种行为原因的想法都将不胜感激 以下是具体细节: 我们对一个模式的四个简单表进

[如果我重复发布此消息,我表示歉意-我以为我上周五发布了一个问题,但我的帐户没有显示任何问题。]

主要问题是:Linux上的Oracle11g在4秒到1.000秒的时间内完成并返回一个特定查询的数据。Oracle在两个不同的执行计划之间来回切换,其中一个执行计划的速度非常缓慢

我们已经确定了对查询的几个语义相同的更改,这使得Oracle不断选择快速执行计划。我们担心由于无明显原因的来回切换而出现错误或数据损坏

任何关于这种行为原因的想法都将不胜感激

以下是具体细节:

我们对一个模式的四个简单表进行了非常简单的Oracle查询。当我们运行这个查询时,执行时间会有很大的不同——如果我们按顺序运行它20次,三到四次执行需要4秒才能返回数据,其他执行需要超过1000秒

我们已经尝试记录执行计划,Oracle在两个不同的执行计划之间进行切换-一个计划给出4秒的响应,另一个给出1.000秒以上的响应

每个表大约有30000行,响应大约为5000行。当Oracle选择慢速执行计划时,获取每个结果行的时间会以指数级的速度变慢—响应的前1000行需要2秒,第1.000-2.000行需要30秒,第2.000-3.000行需要90秒,依此类推

我们在使用的列上有索引,对于快速执行计划,它们按预期使用。慢速计划总是对其中一个索引进行“快速完全扫描”(成本约为2.000),而快速计划则对同一索引进行“范围扫描”(成本约为2)。计划完全不同——可能是因为这个。我们尝试过删除这个索引并重新创建它,但结果没有什么不同

此外,查询在其中一个表的主键列上包含NOT LIKE。如果我们将这些不相似的表达式移到引用列上,Oracle总是选择快速执行计划

我们不想锁定执行计划,因为查询会发生微妙的变化。此外,这种在执行计划之间来回的改变让我们感到担忧——它散发出bug或数据损坏的气味

有人知道为什么甲骨文会这样做吗?除了锁定执行计划之外,还有其他解决方法吗

以下是在快速和慢速执行计划之间切换的查询:

select g.ucid, a.ucid
from account a, groups g, group_members gm, group_groups_flat ggf
where a.ucid = gm.ucid_member
and gm.ucid_group = ggf.ucid_member
and ggf.ucid_group = g.ucid
and a.status = 'active'
and g.unix_gid is not null
and gm.valid_from <= sysdate
and gm.valid_to >= sysdate
and g.ucid not like '$_%' escape '$'
and g.ucid not like 's$_%' escape '$'

你提供的信息有些不一致。在这个问题中,您说一个计划使用
快速全扫描
,而另一个计划对同一索引使用
范围扫描
;但是在dbas站点上的问题版本中,您显示了实际的执行计划,并且两者都使用
快速全扫描
作为唯一基于索引的操作。这两个计划之间的真正区别似乎在于连接顺序,因为要连接的第一个表之间缺少连接条件,所以第二个顺序需要执行一些更大的内存中操作

无论如何,对于如何进一步调查这一点,我有一些建议。一个想法是激活,它记录所有优化器活动,并查看是否可以比较获得两个不同计划的运行结果。输出不是很漂亮,可能很难理解,但它可能会让您了解正在发生的事情


我的另一个想法是,您在查询中使用的唯一非文字值是
SYSDATE
,因此我想知道时间的变化是否会导致优化器的算法发生变化,从而产生不同的计划。我不确定优化器如何处理SYSDATE。您可以尝试使用绑定变量替换对SYSDATE的调用,并在执行查询之前在其他代码中设置日期值。

如果您使用的是11g,则可以使用计划管理来阻止Oracle切换计划


您以前确实问过这个问题,但在-您的问题是。您的帐户似乎没有链接。对于这类问题,这可能是一个更合适的论坛。对不一致之处表示歉意。我连续五天都在思考这个问题——范围扫描实际上是在同一个Oracle实例中以相同的模式(但数据较少)生成的计划。关于SYSDATE的想法非常有趣。我曾尝试用TO_DATE()文本替换SYSDATE,但不幸的是,它没有影响结果。仍然在高效和可怕之间来回变换。
select g.ucid, a.ucid
from account a, groups g, group_members gm, group_groups_flat ggf
where a.ucid = gm.ucid_member
and gm.ucid_group = ggf.ucid_member
and ggf.ucid_group = g.ucid
and a.status = 'active'
and g.unix_gid is not null
and gm.valid_from <= sysdate
and gm.valid_to >= sysdate
and ggf.ucid_group not like '$_%' escape '$'
and ggf.ucid_group not like 's$_%' escape '$'
CREATE TABLE "PDB"."GROUPS"
(
  "UCID"        VARCHAR2(256 BYTE),    
  "UNIX_GID"    NUMBER(*,0),
  [...]

  PRIMARY KEY ("UCID") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE(INITIAL 3145728 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "PDB" ENABLE,

  CONSTRAINT "GN_FK" FOREIGN KEY ("UCID") REFERENCES "PDB"."NAMESPACE" ("UCID") ENABLE
)
CREATE TABLE "PDB"."ACCOUNT"
(
  "UCID"           VARCHAR2(256 BYTE),
  "STATUS"         VARCHAR2(10 BYTE) NOT NULL ENABLE,
  [...]

  PRIMARY KEY ("UCID") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE(INITIAL 2097152 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "PDB" ENABLE,

  FOREIGN KEY ("STATUS") REFERENCES "PDB"."ACCOUNT_STATUS" ("STATUS") ENABLE,
  CONSTRAINT "AN_FK" FOREIGN KEY ("UCID") REFERENCES "PDB"."NAMESPACE" ("UCID") ENABLE,
)
CREATE TABLE "PDB"."GROUP_MEMBERS"
(
  "UCID_GROUP"  VARCHAR2(256 BYTE) NOT NULL ENABLE,
  "UCID_MEMBER" VARCHAR2(256 BYTE) NOT NULL ENABLE,
  "VALID_FROM" DATE NOT NULL ENABLE,
  "VALID_TO" DATE NOT NULL ENABLE,
  CONSTRAINT "GROUP_MEMBERS_GROUPS_FK1" FOREIGN KEY ("UCID_GROUP") REFERENCES "PDB"."GROUPS" ("UCID") ENABLE,
  CONSTRAINT "GROUP_MEMBERS_MEMBER_FK1" FOREIGN KEY ("UCID_MEMBER") REFERENCES "PDB"."ACCOUNT" ("UCID") ENABLE
)
CREATE INDEX "PDB"."IDX_GROUP_MEMBERS_FROM" ON "PDB"."GROUP_MEMBERS"("VALID_FROM")
CREATE INDEX "PDB"."IDX_GROUP_MEMBERS_TO" ON "PDB"."GROUP_MEMBERS"("VALID_TO")
CREATE TABLE "PDB"."GROUP_GROUPS_FLAT"
(
  "UCID_GROUP"  VARCHAR2(256 BYTE),
  "UCID_MEMBER" VARCHAR2(256 BYTE),
  CONSTRAINT "GROUP_GROUPS_FLAT_GROUPS_FK1" FOREIGN KEY ("UCID_GROUP") REFERENCES "PDB"."GROUPS" ("UCID") ENABLE,
  CONSTRAINT "GROUP_GROUPS_FLAT_GROUPS_FK2" FOREIGN KEY ("UCID_MEMBER") REFERENCES "PDB"."GROUPS" ("UCID") ENABLE
)
CREATE INDEX "PDB"."IDX_GROUP_GROUPS_FLAT_GROUP" ON "PDB"."GROUP_GROUPS_FLAT("UCID_GROUP")
CREATE INDEX "PDB"."IDX_GROUP_GROUPS_FLAT_MEMBER" ON "PDB"."GROUP_GROUPS_FLAT("UCID_MEMBER")