Ora2pg分区索引转换
Oracle Local索引类型与Postgresql分区表的索引类似: 1.Oracle在分区表上创建LOCAL索引同步会在其子分区表上面创建相同数量的索引;Postgresql在分区主表创建索引,同样也在各子表上创建索引;Postgresql可以在分区子表中单创建索引。 2.在查询时,查询条件包括分区键都是先通过过滤分区键定位至具体的子分区,然后根据创建的索引在子分区内部进行索引扫描查询;
测试数据
--创建分区表(oracle)
CREATE TABLE measurement (
city_id int not null,
logdate date not null,
peaktemp int,
unitsales int
) PARTITION BY RANGE (logdate)
(
partition y2018 values less than (to_date('2018-01-01','yyyy-MM-dd')),
partition y2019 values less than (to_date('2019-01-01','yyyy-MM-dd')) ,
partition y2020 values less than (to_date('2020-01-01','yyyy-MM-dd')) ,
partition ymaxvalue values less than (maxvalue)
);
--创建分区表(postgresql)
CREATE TABLE measurement(
city_id numeric,
logdate timestamp,
peaktemp numeric,
unitsales numeric,
CHECK(city_id IS NOT NULL),
CHECK(logdate IS NOT NULL))PARTITION BY RANGE (logdate);
CREATE TABLE measurement_y2018 PARTITION OF measurement (logdate) FOR VALUES FROM (MINVALUE) TO ('2018-01-01') ;
CREATE TABLE measurement_y2019 PARTITION OF measurement (logdate) FOR VALUES FROM ('2018-01-01') TO ('2019-01-01') ;
CREATE TABLE measurement_y2020 PARTITION OF measurement (logdate) FOR VALUES FROM ('2019-01-01') TO ('2020-01-01') ;
CREATE TABLE measurement_ymaxvalue PARTITION OF measurement (logdate) FOR VALUES FROM ('2020-01-01') TO (maxvalue)
查询条件只有分区键logdate
select * from measurement where logdate=to_date('2019-03-19','yyyy-MM-dd');--查询条件只有分区键logdate
创建Oracle Local分区索引,各个子分区创建索引
--oracle
create index idx_measurement_logdate on measurement(logdate) local;
--各个子分区创建索引
SQL> select INDEX_NAME,PARTITION_NAME,HIGH_VALUE,STATUS from dba_ind_partitions where index_name=upper('idx_measurement_logdate');
INDEX_NAME PARTITION_NAME HIGH_VALUE STATUS
------------------------------ ------------------------------ -------------------------------------------------------------------------------- --------
IDX_MEASUREMENT_LOGDATE Y2018 TO_DATE(' 2018-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USABLE
IDX_MEASUREMENT_LOGDATE Y2019 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USABLE
IDX_MEASUREMENT_LOGDATE Y2020 TO_DATE(' 2020-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USABLE
IDX_MEASUREMENT_LOGDATE YMAXVALUE MAXVALUE USABLE
--开启跟踪
set autotrace on;
--oracle执行计划
SQL> explain plan for select * from measurement where logdate=to_date('2019-03-19','yyyy-MM-dd');
Explained
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1483329978
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | B
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
| 1 | PARTITION RANGE SINGLE | | 1 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| MEASUREMENT | 1 |
|* 3 | INDEX RANGE SCAN | IDX_MEASUREMENT_LOGDATE | 1 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("LOGDATE"=TO_DATE(' 2019-03-19 00:00:00', 'syyyy-mm-dd hh24:mi:ss'
Note
-----
- dynamic sampling used for this statement (level=2)
--先进入具体子分区,再通过分区子表索进行索引扫描查询
PARTITION RANGE SINGLE表示只扫描单个分区TABLE ACCESS BY LOCAL INDEX ROWID表示通过索引扫描分区内的数据
创建postgresql索引,各子表分区自动创建索引
--postgresql
CREATE INDEX idx_measurement_logdate ON measurement(logdate);
--各个子分区创建索引
postgres=# select * from pg_indexes where tablename like '%measurement%' order by tablename;
schemaname | tablename | indexname | tablespace | indexdef
------------+-----------------------+-----------------------------------+------------+-----------------------------------------------------------------
-------------------------------------
public | measurement_y2018 | measurement_y2018_logdate_idx | | CREATE INDEX measurement_y2018_logdate_idx ON public.measurement
_y2018 USING btree (logdate)
public | measurement_y2019 | measurement_y2019_logdate_idx | | CREATE INDEX measurement_y2019_logdate_idx ON public.measurement
_y2019 USING btree (logdate)
public | measurement_y2020 | measurement_y2020_logdate_idx | | CREATE INDEX measurement_y2020_logdate_idx ON public.measurement
_y2020 USING btree (logdate)
public | measurement_ymaxvalue | measurement_ymaxvalue_logdate_idx | | CREATE INDEX measurement_ymaxvalue_logdate_idx ON public.measure
ment_ymaxvalue USING btree (logdate)
(4 rows)
--postgresql执行计划
postgres=# explain select * from measurement where logdate=to_date('2019-03-19','yyyy-MM-dd');
QUERY PLAN
--------------------------------------------------------------------------------------------------
Append (cost=4.18..45.22 rows=12 width=104)
Subplans Removed: 3
-> Bitmap Heap Scan on measurement_y2020 (cost=4.18..11.29 rows=3 width=104)
Recheck Cond: (logdate = to_date('2019-03-19'::text, 'yyyy-MM-dd'::text))
-> Bitmap Index Scan on measurement_y2020_logdate_idx (cost=0.00..4.18 rows=3 width=0)
Index Cond: (logdate = to_date('2019-03-19'::text, 'yyyy-MM-dd'::text))
(6 rows)
--先进入measurement_y2020分区,再通过分区子表索引measurement_y2020_logdate_idx进行索引扫描查询
总结:这种情况下oracle和postgresql基本都是先扫描到具体的分区子表,再在子表里通过索引进行查询;
查询条件有区分键也有非分区键
select * from measurement where logdate=to_date('2019-03-19','yyyy-MM-dd') and city_id=1;--查询条件有区分键也有非分区键
–oracle,都会在各个子分区创建索引 create index idx_measurement_peaktemp_city_id on measurement(city_id) local;
–postgresql,同步在各个子分区创建索引 CREATE INDEX idx_measurement_peaktemp_city_id ON measurement(city_id);