0

我正在修改原始问题,因为更改的条件很少 - 我在 Oracle11g 上运行以下查询,显示结果需要 27 秒。任何人都可以建议改善查询响应时间的解决方案吗?我在下面提供相关细节 -

select  Column1 , round(count(Column2)/10) 
from SE_CA 
where Column3 <= 4855 
and Column4 > 4490
group by Column1;

SE_CA table has total 123914265 records.

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3324421310

-------------------------------------------------
| Id  | Operation          | Name  | Cost (%CPU)|
-------------------------------------------------
|   0 | SELECT STATEMENT   |       |   211K  (3)|
|   1 |  HASH GROUP BY     |       |   211K  (3)|
|*  2 |   TABLE ACCESS FULL| SE_CA |   208K  (1)|
-------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   2 - filter("Column3"<=4855 AND "Column4">4490)



SQL> desc SE_CA;
Name                                      Null?     Type
Column1                                             VARCHAR2(3)
Column2                                             NUMBER
Column3                                             NUMBER
Column4                                             NUMBER
Column5                                             NUMBER
Column6                                             NUMBER
Column7                                             NUMBER
Column8                                             NUMBER
Column9                                             VARCHAR2(5)
Column10                                            VARCHAR2(12)


Index Definition -

CREATE  INDEX IDX1_SE_CA ON SE_CA(Column3);
CREATE  INDEX IDX2_SE_CA ON SE_CA(Column4);
CREATE  INDEX IDX4_SE_CA ON SE_CA(Column1);
  • 应用这两个条件后,预期输出约为整个表行(10581643 行)的 10%。
  • 单独应用每个条件后,第 3 列的输出为 10581643,第 4 列的输出为 12391426。
  • Column3 的最小值和最大值分别为 4623 和 4988。
  • 而第 4 列的最小值和最大值分别为 4624 和 4991。

你能告诉我创建的索引是否正确还是我需要不同的索引?

4

1 回答 1

0

了解您是否可以提高此查询的性能的关键是了解有关数据的一些基本统计信息。

  1. 您有谓词(max,min)的两列的值范围是多少?
  2. 您期望有多少百分比的行单独满足每个条件?
  3. 您期望有多少百分比的行同时满足这两个条件?

如果谓词 Column3 <= 4855 将包括表的 30% 的行,那么全表扫描或快速全索引扫描将是优化器的最佳选择,如果这是表上唯一的谓词

现在,可能是谓词 Column4 > 4490 将包括表的 90% 的行——仅基于这一点,优化器可能会得出结论,当两个谓词都存在时,要检索的行的比例是0.3 * 0.9 = 27%。这仍然表明完全扫描是合适的。

然而,这两个值之间可能存在相关性,例如 column1 的低值很少有 column2 的高值,并且只有 3% 的行满足该条件。在这种情况下,可能值得尝试使用基于索引的访问方法。

这是优化器动态采样可以通过包含优化器提示来检测的情况:

select /*+ dynamic_sampling(SE_CA 4) */  Column1 , ...

因此,获得有关值分布的这些问题的答案,并尝试动态采样——这个查询看起来是一个很好的候选者,因为我认为“EXPOSED_TIME”和“INFECTIOUS_TIME”之间存在相关性;)

更远

由于您希望从表中检索大约 10% 的行,因此基于索引的访问表的方法不太可能会有所帮助。即使是索引范围扫描也可能不如优化器选择的索引快速全扫描那么有效。这将取决于 i/o 子系统的效率以及单块和多块 i/o 的相对速度。(你能确保段空间是自动分配的或以至少 1MB 为单位均匀分配的吗?)

但是,如果您有可用的分区选项,则可以在 EXPOSED_TIME 上对该表进行范围分区,以允许更有效的分区修剪扫描以选择表行的子集。然而,这是一个很大的改变,并且必须非常小心地考虑对其他操作的副作用。

您可能还考虑使用低程度的查询并行性,尽管这也有副作用(段级检查点,这可能会对当时发生大量更改的表产生负面影响) .

于 2013-04-18T07:54:14.950 回答