【发布时间】:2014-10-15 19:57:33
【问题描述】:
我在 Oracle 11g 文档和论坛中搜索了有关如何获取此视图和查询以使用基于函数的索引的示例,但到目前为止我还没有找到。感谢您的帮助。
我使用的应用程序不支持直接查询的 TIMESTAMP 数据类型,但如果它在视图中转换为 DATE,则支持该数据类型。但是,我必须使用时间戳函数查询这个转换列。这有点像往返。第 3 方应用程序发送我在 SQL*Plus/SQL Developer 中使用的相同查询,并显示在下面。
我实际上并不需要 TIMESTAMP 数据类型的小数秒粒度,只是出于数据供应商的原因需要在此数据库中使用它。
我了解在将函数应用于该列时不使用列索引。我无法完成的是构建一个适当的基于函数的索引,以避免对数百万行进行全表扫描(根据表,在 200 万到 6 亿行之间)。我不想使用提示,但在这一点上,任何事情都比全表扫描更好,我愿意接受所有建议。
这是所需的视图:
SELECT
CAST(SAMPLE_TABLE.TIMESTAMP_COLUMN as DATE) as TIMESTAMP_COLUMN
FROM TEST_USER.SAMPLE_TABLE;
这是一个带有解释计划前缀的示例查询:
explain plan for
select * FROM SAMPLE_VIEW WHERE TIMESTAMP_COLUMN = timestamp '2010-08-10 12:00:00';
select plan_table_output
from table(dbms_xplan.display('plan_table',null,'all'));
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 200K| 1562K| 169K (1)| 00:33:56 | | |
| 1 | PARTITION LIST ALL | | 200K| 1562K| 169K (1)| 00:33:56 | 1 | 6 |
| 2 | PARTITION RANGE ALL| | 200K| 1562K| 169K (1)| 00:33:56 | 1 | 49 |
|* 3 | TABLE ACCESS FULL | SAMPLE_TABLE | 200K| 1562K| 169K (1)| 00:33:56 | 1 | 294 |
-----------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$F5BB74E1
3 - SEL$F5BB74E1 / SAMPLE_TABLE@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(INTERNAL_FUNCTION(CAST(INTERNAL_FUNCTION("TIMESTAMP_COLUMN") AS DATE))=TIMESTAMP_COLUMN'
2010-08-10 12:00:00.000000000')
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "TIMESTAMP_COLUMN"[TIMESTAMP WITH LOCAL TIME ZONE,11]
2 - "TIMESTAMP_COLUMN"[TIMESTAMP WITH LOCAL TIME ZONE,11]
3 - "TIMESTAMP_COLUMN"[TIMESTAMP WITH LOCAL TIME ZONE,11]
当然,只要我从视图中删除 Cast 函数,索引就会按预期使用:
改变视图:
SELECT
TIMESTAMP_COLUMN
FROM TEST_USER.SAMPLE_TABLE;
相同的查询:
explain plan for
select * FROM SAMPLE_VIEW WHERE TIMESTAMP_COLUMN = timestamp '2010-08-10 12:00:00';
select plan_table_output
from table(dbms_xplan.display('plan_table',null,'all'));
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 22 | 3 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| TIMESTAMP_COL_IDX | 2 | 22 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$F5BB74E1 / SAMPLE_TABLE@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("TIMESTAMP_COLUMN"=TIMESTAMP' 2010-08-10 12:00:00.000000000')
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "TIMESTAMP_COLUMN"[TIMESTAMP WITH LOCAL TIME ZONE,11]
这是在没有强制转换函数的情况下使用的普通索引 DDL (TIMESTAMP_COL_IDX)。我使用 SQL Developer 的 GUI 构建了它:
CREATE INDEX "TEST_USER"."TIMESTAMP_COL_IDX" ON "TEST_USER"."SAMPLE_TABLE" ("TIMESTAMP_COLUMN")
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 "TEST" ;
这是我无法调用的基于函数的索引 DDL,可能写得不正确:
CREATE INDEX "TEST_USER"."TIMESTAMP_FBI_IDX" ON "TEST_USER"."SAMPLE_TABLE" (CAST("TIMESTAMP_COLUMN" AS DATE))
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 "TEST" ;
我已经收集了视图所基于的表的统计信息,但在 11g 中,我认为在构建索引后这不是“必需的”。它没有改变执行计划。
谢谢。
编辑#1
当我说:“但是,我必须使用时间戳函数查询这个转换列。这有点像往返。”...
...我应该澄清我需要使用的整个工作流程,这是导致这种情况的原因。以下是按时间顺序排列的工作流程:
- 数据以 TIMESTAMP 格式传送到 Oracle 数据库,并且必须按此格式存储。
- Web 发布应用程序不支持 TIMESTAMP 但允许 DATE,因此使用 Cast。
- Web 查询应用程序必须查询为 TIMESTAMP 或使用 DATE 的时间戳功能。
这就是我所说的数据“往返”的意思;数据库和 Web 应用程序都使用 TIMESTAMP,但发布到 Web 应用程序的中间件不能,从而导致这种昂贵的转换场景,导致全表扫描。
【问题讨论】:
-
那么您需要使用时间戳和日期数据类型来查询视图吗?并且视图列必须与两个查询使用的完全相同?
-
如果您使用日期查询但您在此处提供时间戳,那么基于函数的索引应该可以工作,因此它又是不同的数据类型...
标签: database oracle view casting indexing