Давно уж думал о том, что пора бы ораклу обзавестись пользовательскими типами индексов, а за не имением оных попробовать fbi на spatial индексе, то бишь на r-tree. И вот решил попробовать, да не вышло...
» Код 1: «
create or replace function dates_interval(d_start in date, d_final in date)
return mdsys.sdo_geometry
deterministic
as
begin
return
mdsys.sdo_geometry(
2002, /* SDO_GTYPE:
dl02 == TWO DIMENSION LINE:
d identifies the number of dimensions (2, 3, or 4)
l identifies the linear referencing measure dimension
for a three-dimensional linear referencing system (LRS)
geometry, that is, which dimension (3 or 4) contains
the measure value. For a non-LRS geometry, or to
accept the Spatial default of the last dimension as
the measure for an LRS geometry, specify 0.
02 LINE or CURVE: Geometry contains one line string that
can contain straight or circular arc segments, or both.
(LINE and CURVE are synonymous in this context.)
*/
NULL, -- coordinate system (spatial reference system)
-- If SDO_SRID is null, no coordinate system is associated with the geometry.
NULL, /* SDO_POINT,
If the SDO_ELEM_INFO and SDO_ORDINATES arrays are both null, and the SDO_POINT
attribute is non-null, then the X and Y values are considered to be the
coordinates for a point geometry. Otherwise, the SDO_POINT attribute is ignored
by Spatial. You should store point geometries in the SDO_POINT attribute for
optimal storage; and if you have only point geometries in a layer,
it is strongly recommended that you store the point geometries in the SDO_POINT attribute.
*/
mdsys.sdo_elem_info_array (
1 --SDO_STARTING_OFFSET
,2 --SDO_ETYPE: 2 - line string
-- http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14255/sdo_objrelschema.htm#BGHDGCCE
,1 --SDO_INTERPRETATION:
-- 1 for SDO_ETYPE=2 == Line string whose vertices are connected by straight line segments.
),
SDO_ORDINATE_ARRAY(
to_number(to_char(d_start,'yyyymmddhh24miss'))
,0 -- all will be on y=0
,to_number(to_char(d_final,'yyyymmddhh24miss'))
,0
)
);
end;
/
create table rtree(
d_start date,
d_final date,
stat number
)
/
create index dates_fbi on rtree(
dates_interval(d_start,d_final)
)
INDEXTYPE IS MDSYS.SPATIAL_INDEX
/
* This source code was highlighted with Source Code Highlighter.
Ошибка дурацкая:
DB11G/XTENDER> create index dates_fbi on rtree(
2 dates_interval(d_start,d_final)
3 )
4 INDEXTYPE IS MDSYS.SPATIAL_INDEX;
create index dates_fbi on rtree(
*
ERROR at line 1:
ORA-29855: error occurred in the execution of ODCIINDEXCREATE routine
ORA-13203: failed to read USER_SDO_GEOM_METADATA view
ORA-13203: failed to read USER_SDO_GEOM_METADATA view
ORA-06512: at "MDSYS.SDO_INDEX_METHOD_10I", line 10
UPD:Разобрался, проблема оказалась в необходимости для этого метаданных: в "select * from user_sdo_geom_metadata;" должны быть данные о колонках с метаданными о spatial данных, а так как в моем примере колонки такой и нет, то и использовать это не получилось бы.
Тем не менее я все-таки проверил насколько хорошо spatial index будет работать для диапазонов-создал табличкуc 20 тыс. равномерных диапазонов дат - оказался обычный фулскан по датам быстрее, чем поиск по spatial индексу...
» Код «
drop table rtree purge
/
create table rtree(
stat number,
sdo_dates mdsys.sdo_geometry
)
/
--вставляем метаданные о колонке таблицы - именно то из-за чего была ошибка в первом примере
insert into USER_SDO_GEOM_METADATA (table_name,column_name,srid,diminfo)
values(
'RTREE',
'SDO_DATES',
null,
SDO_DIM_ARRAY (
SDO_DIM_ELEMENT(
'X',
19900000000000,
21000000000000,
1
),
SDO_DIM_ELEMENT(
'Y',
0,
0,
1
)
)
)
/
--заполним быстренько:
insert into rtree
select rownum,
dates_interval(
to_date('01.01.2009','dd.mm.yyyy')+level,
to_date('02.01.2009','dd.mm.yyyy')+level+1
)
from dual
connect by level<20000
/
--создадим индекс:
create index dates_fbi on rtree( sdo_dates )
INDEXTYPE IS MDSYS.SPATIAL_INDEX
/
-- ну и проверка времени поиска:
select * from rtree r
where SDO_RELATE( r.sdo_dates
,dates_interval(sysdate-1,sysdate)
,'mask=ANYINTERACT querytype=WINDOW'
) = 'TRUE';
* This source code was highlighted with Source Code Highlighter.
» Код проверки обычного фуллскана по обычным датам: «
create table rtest as
select rownum id,
to_date('01.01.2009','dd.mm.yyyy')+level d_start,
to_date('02.01.2009','dd.mm.yyyy')+level+1 d_end
from dual
connect by level<20000
/
select * from rtest where trunc(sysdate+5000)>=d_start and trunc(sysdate-1+5000)<=d_end
* This source code was highlighted with Source Code Highlighter.
Comments
Отправить комментарий