【发布时间】:2014-03-06 14:10:21
【问题描述】:
我有一张桌子A,间隔(COL1, COL2):
CREATE TABLE A (
COL1 NUMBER(15) NOT NULL,
COL2 NUMBER(15) NOT NULL,
VAL1 ...,
VAL2 ...
);
ALTER TABLE A ADD CONSTRAINT COL1_BEFORE_COL2 CHECK (COL1 <= COL2);
保证间隔是“独占的”,即它们永远不会重叠。换句话说,这个查询不会产生任何行:
SELECT *
FROM (
SELECT
LEAD(COL1, 1) OVER (ORDER BY COL1) NEXT,
COL2
FROM A
)
WHERE COL2 >= NEXT;
目前在(COL1, COL2) 上有一个索引。现在,我的查询如下:
SELECT /*+FIRST_ROWS(1)*/ *
FROM A
WHERE :some_value BETWEEN COL1 AND COL2
AND ROWNUM = 1
这对于:some_value 的低值表现良好(A 中的数百万条记录不到一毫秒),因为它们对索引非常有选择性。但是对于 :some_value 的高值,由于访问谓词的选择性较低,它的性能很差(几乎是一秒钟)。
执行计划对我来说似乎不错。由于现有索引已经完全覆盖了谓词,我得到了预期的INDEX RANGE SCAN:
------------------------------------------------------
| Id | Operation | Name | E-Rows |
------------------------------------------------------
| 0 | SELECT STATEMENT | | |
|* 1 | COUNT STOPKEY | | |
| 2 | TABLE ACCESS BY INDEX ROWID| A | 1 |
|* 3 | INDEX RANGE SCAN | A_PK | |
------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM=1)
3 - access("VAL2">=:some_value AND "VAL1"<=:some_value)
filter("VAL2">=:some_value)
在3 中,很明显,访问谓词仅对:some_value 的低值具有选择性,而对于较高的值,过滤操作会“启动”索引。
无论:some_value 的值如何,有什么方法可以普遍提高这个查询的速度吗?如果需要进一步规范化,我可以完全重新设计表格。
【问题讨论】: