Ora2pg之分区索引转换

tech2023-02-11  111

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);

最新回复(0)