Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 聚合视图中的Oracle索引使用情况_Sql_Oracle_Optimization_Plsql_Indexing - Fatal编程技术网

Sql 聚合视图中的Oracle索引使用情况

Sql 聚合视图中的Oracle索引使用情况,sql,oracle,optimization,plsql,indexing,Sql,Oracle,Optimization,Plsql,Indexing,背景如下: 版本: Oracle 8i(不要因为我过时而恨我。我们正在升级!) 下面是一个立即返回的查询: SQL> select to_char(trunc(day,'HH'),'DD-MON-YYYY HH24') day, 2 avg(decode(stone,-9999,null,stone)) stone, 3 avg(decode(simpson,-9999,null,simpson)) simpson, 4 avg(decode(oxychem,-9999,null,o

背景如下:

版本: Oracle 8i(不要因为我过时而恨我。我们正在升级!)

下面是一个立即返回的查询:

SQL> select to_char(trunc(day,'HH'),'DD-MON-YYYY HH24') day,
2  avg(decode(stone,-9999,null,stone)) stone,
3  avg(decode(simpson,-9999,null,simpson)) simpson,
4  avg(decode(oxychem,-9999,null,oxychem)) oxychem,
5  avg(decode(praxair,-9999,null,praxair)) praxair
6  from IDcpdata
7  where day between
8  to_date('14-jun-2009 0','dd-mon-yyyy hh24') and
9  to_date('14-jun-2009 13','dd-mon-yyyy hh24')
10  group by trunc(day,'HH');
当我基于该查询创建一个视图时,如果没有where子句,则针对该视图的带有where子句的查询将无法使用该视图。直接SQL查询版本中使用了高选择性索引。全表扫描需要20分钟

create or replace view theview as
select TRUNC(day,'HH') day, 
avg(decode(stone,-9999,null,stone)) stone, 
avg(decode(simpson,-9999,null,simpson)) simpson, 
avg(decode(oxychem,-9999,null,oxychem)) oxychem, 
avg(decode(praxair,-9999,null,praxair)) praxair 
from IDcpdata group by TRUNC(day,'HH');


SQL> select * from theview
2  where day between
3  to_date('14-jun-2009 0','dd-mon-yyyy hh24') and
4  to_date('14-jun-2009 13','dd-mon-yyyy hh24');
我在视图、查询和两者中尝试了INDEX()提示。我尝试了全局索引提示,指定了基础表的完全限定名。我也试过合并

在我看来,Oracle应该能够使用索引,因为内联SQL可以。我就是不知道该怎么强迫它。我肯定是我,不是神谕,我只是没看见而已


提前感谢您的建议

您的视图查询在
TRUNC(day,'HH')
上过滤,而不是在
day
上过滤

由于您将视图定义为将
TRUNC(day,'HH')返回为day
,因此它是
BETWEEN
子句应用到的截断的day值,不可搜索

TRUNC(day,'HH')上创建索引

更新:

这适用于我的
Oracle 10g XE

CREATE TABLE t_group (id INT NOT NULL PRIMARY KEY, day DATE NOT NULL)
/

INSERT
INTO    t_group
SELECT  level, TRUNC(SYSDATE) - level
FROM    dual
CONNECT BY
        level <= 100
/

CREATE INDEX ix_group_truncday ON t_group (TRUNC(day, 'HH'))
/

CREATE VIEW v_group AS
SELECT  TRUNC(day, 'HH') AS day
FROM    t_group
GROUP BY
        TRUNC(day, 'HH')
/

EXPLAIN PLAN FOR
SELECT  *
FROM    v_group
WHERE   day BETWEEN TO_DATE('01.08.2009', 'dd.mm.yyyy') AND TO_DATE('02.08.2009', 'dd.mm.yyyy')
/

SELECT  *
FROM    TABLE(DBMS_XPLAN.display)
/

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1656741214
--------------------------------------------------------------------------------
| Id  | Operation                    | Name              | Rows  | Bytes | Cost
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                   |     1 |     9 |     2
|   1 |  HASH GROUP BY               |                   |     1 |     9 |     2
|   2 |   TABLE ACCESS BY INDEX ROWID| T_GROUP           |     1 |     9 |     1
|*  3 |    INDEX RANGE SCAN          | IX_GROUP_TRUNCDAY |     1 |       |     1
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access(TRUNC(INTERNAL_FUNCTION("DAY"),'fmhh')>=TO_DATE('2009-08-01 00:00:
              'yyyy-mm-dd hh24:mi:ss') AND TRUNC(INTERNAL_FUNCTION("DAY"),'fmhh'
              00:00:00', 'yyyy-mm-dd hh24:mi:ss'))

17 rows selected
CREATE TABLE t_组(id INT NOT NULL主键,day DATE NOT NULL)
/
插入
进入t_组
选择级别,TRUNC(SYSDATE)-级别
来自双重
通过连接
级别=截止日期('2009-08-01 00:00:00:00:00:00:00:00:00:00:00:00:00:00)
“yyyy-mm-dd hh24:mi:ss”)和TRUNC(内部功能(“日”),“fmhh”
00:00:00',yyyy-mm-dd hh24:mi:ss'))
选定17行
在第一种情况下,WHERE子句中的“天”引用表列“天”,而不是查询结果列“天”,因此可以使用索引,但结果不包括2009年6月14日13:00:01以后的数据

在第二种情况下,WHERE子句中的“day”引用视图列“day”,该列被定义为TRUNC(day,'HH')。因此,这不能使用索引,包含2009年6月14日13:00:01以后的数据-即,这两个查询不相等

您可能希望实现这两种方法的最佳效果:

create or replace view theview as
select day,
TRUNC(day,'HH') trunc_day, 
avg(decode(stone,-9999,null,stone)) stone, 
avg(decode(simpson,-9999,null,simpson)) simpson, 
avg(decode(oxychem,-9999,null,oxychem)) oxychem, 
avg(decode(praxair,-9999,null,praxair)) praxair 
from IDcpdata group by TRUNC(day,'HH');

SQL> select trunc_day, stone, simpson, oxychem, pracair
2  from theview
3  where day >= to_date('14-jun-2009 0','dd-mon-yyyy hh24')
4  and day < to_date('14-jun-2009 13','dd-mon-yyyy hh24');
create index IDcpdata_truncday_idx ON IDcpdata (TRUNC(day,'HH'));

在IDcpdata(TRUNC(day,'HH')
上构建基于函数的索引
的建议是合理的。有其他基于函数的索引吗?如果不是,这也许可以解释为什么优化器不使用它

这种索引类型是在8i中引入的,因此当时的实现有点笨拙。具体来说,您需要设置一些数据库参数,否则优化器将忽略索引

ALTER SESSION SET QUERY_REWRITE_INTEGRITY = TRUSTED; 
ALTER SESSION SET QUERY_REWRITE_ENABLED = TRUE;
我想你还需要用8i计算统计数据


(我要感谢谷歌和蒂姆·霍尔,他们代理了我的记忆力衰退)。

没错,因为这就是我想要的聚合。我将其向下移动到视图中,因此我认为优化器会发现仍然可以使用索引。你是说我的查询应该是SQL>从视图2中选择*,其中trunc(day,'HH')介于3到_日期('2009年6月14日0','dd-mon-yyyyyh24')和4到_日期('2009年6月14日13','dd-mon-yyyyyyyh24');或者我就是不能提出一个可行的观点?谢谢<代码>@Ian
:是。在本例中,
day
应该是从表中返回的原始
day
。我创建了确切的索引,但没有使用它。即使有暗示!在查询中包含日期会导致该日期未按截断的日期分组。您的示例无法编译,因为DAY未包含在GROUP BY子句中。
@Ian
:对,我没有注意到您查询中的
GROUP BY
。看到这篇文章更新了。@Tony:我也考虑过,但它不会编译:day不是你的create view语句中的聚合。是的,我也是。问题是我希望数据按小时聚合,包括查询中未截断的日期,需要将其包含在group by子句中。您是对的!唯一真正的问题是为什么它不使用我的函数索引,一旦我意识到通过将聚合推到视图中,我就不能再使用基值上的索引了。那些神秘的甲骨文咒语释放了功能索引的力量,我很高兴。非常感谢。
create index IDcpdata_truncday_idx ON IDcpdata (TRUNC(day,'HH'));
ALTER SESSION SET QUERY_REWRITE_INTEGRITY = TRUSTED; 
ALTER SESSION SET QUERY_REWRITE_ENABLED = TRUE;