Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Удалить записи с сохранением партиций / 18 сообщений из 18, страница 1 из 1
07.02.2019, 20:07
    #39770829
Landgraf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
Ребята всем привет!

Нужен ваш совет.
Есть таблица размером в 800 Гб. Она партицирована по полю dDate (тип дата). Нужно удалить все записи у которых dDate < 01.01.17.

Учитывая размер таблицы, оператор delete будет работать очень долго.
Думал над таким вариантом:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
Create table MyTable_tmp as
select * from MyTable where dDate >= 01.01.17;

Truncate table MyTable;

Insert into mytable
Select * from mytable_p



Но при таком варианте пропадает партицирование.
Как бы сделать так, чтобы партицирование не слетели по оставшимся записям?
...
Рейтинг: 0 / 0
07.02.2019, 20:10
    #39770831
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
LandgrafОна партицирована по полю dDate (тип дата).С какой целью партиционировали таблицу?
...
Рейтинг: 0 / 0
07.02.2019, 20:17
    #39770834
Landgraf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
-2-LandgrafОна партицирована по полю dDate (тип дата).С какой целью партиционировали таблицу?

На сколько мне известно, на основании этого поля строятся отчёты. Поле хранит дату загрузки данных. Т.е. за каждый день присутствует N записей.
Таблица была сделана до меня, поэтому почему ее партиционировали.... Для скорости наверное :)
...
Рейтинг: 0 / 0
07.02.2019, 21:23
    #39770853
jan2ary
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
Landgraf,

Транкейтить партиции?
...
Рейтинг: 0 / 0
08.02.2019, 00:32
    #39770878
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
Помолясь и запасясь бэкапом...

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
create or replace function EVALUATE( s in varchar ) return date as
  res date;
begin
  execute immediate 'begin :x := '||s||'; end;' using out res;
  return res;
end;
/

Function created

create table dropme_t(id, val, dDate)
partition by range(dDate)
interval (interval '11' day)
(partition p1 values less than (date'2000-01-01') segment creation deferred)
as select rownum, 'val'||rownum, date'2016-12-01'+rownum from dual connect by level < 200
;

Table created

select count(*) "ВСЕГО"
     , count(case when ddate <  date'2017-01-01' then 1 end) "Удалить"
     , count(case when ddate >= date'2017-01-01' then 1 end) "Сохранить"
from dropme_t;

     ВСЕГО    Удалить  Сохранить
---------- ---------- ----------
       199         30        169

-- Пограничный раздел
select * from dropme_t partition for (date'2017-01-01');

        ID VAL                                         DDATE
---------- ------------------------------------------- -----------
        25 val25                                       26.12.2016
        26 val26                                       27.12.2016
        27 val27                                       28.12.2016
        28 val28                                       29.12.2016
        29 val29                                       30.12.2016
        30 val30                                       31.12.2016
        31 val31                                       01.01.2017
        32 val32                                       02.01.2017
        33 val33                                       03.01.2017
        34 val34                                       04.01.2017
        35 val35                                       05.01.2017
11 rows selected

-- Поехали...
declare
  l_owner varchar2(100) := USER;
  l_name varchar2(100) := 'DROPME_T';
  l_keep_after date := date'2017-01-01';
  l_partkeyexpression varchar2(2000) := to_char(l_keep_after,q'{"TO_DATE('"yyyy-mm-dd hh24:mi:ss"','yyyy-mm-dd hh24:mi:ss')"}');
  l_meta xmltype;
begin
  l_meta := xmltype(dbms_metadata.get_xml('TABLE',l_name,l_owner));
  for i in (
    select interval_str
    from xmltable('/ROWSET/ROW/TABLE_T/PART_OBJ/PARTOBJ'
           passing l_meta
           columns interval_str path 'INTERVAL_STR'
         )
  )loop
    if i.interval_str is not null then
      execute immediate 'alter table '||l_owner||'.'||l_name||' set interval()';
      execute immediate 'alter table '||l_owner||'.'||l_name||' set interval('||i.interval_str||')';
    end if;
  end loop;
  for i in (
    select 'alter table DROPME_T drop partition '||part_name||' update indexes' stmnt
      from xmltable('/ROWSET/ROW/TABLE_T/PART_OBJ/PART_LIST/PART_LIST_ITEM'
      passing l_meta
      columns part_name path 'SCHEMA_OBJ/SUBNAME'
            , HIBOUNDVAL path 'HIBOUNDVAL'
      ) x
      where evaluate(hiboundval) <= l_keep_after
    ) loop
      execute immediate ''||i.stmnt;
    end loop;
    execute immediate 'alter table '||l_owner||'.'||l_name||' split partition for('||l_partkeyexpression||') at ('||l_partkeyexpression||') update indexes';
    execute immediate 'alter table '||l_owner||'.'||l_name||q'{ drop partition for(date'1900-01-01') update indexes}';
end;
/

PL/SQL procedure successfully completed

-- Итог: 
select count(*) "ВСЕГО"
     , count(case when ddate <  date'2017-01-01' then 1 end) "Удалить"
     , count(case when ddate >= date'2017-01-01' then 1 end) "Сохранить"
from dropme_t;

     ВСЕГО    Удалить  Сохранить
---------- ---------- ----------
       169          0        169

select * from dropme_t partition for (date'2017-01-01');
        ID VAL                                         DDATE
---------- ------------------------------------------- -----------
        31 val31                                       01.01.2017
        32 val32                                       02.01.2017
        33 val33                                       03.01.2017
        34 val34                                       04.01.2017
        35 val35                                       05.01.2017

SQL> 

...
Рейтинг: 0 / 0
11.02.2019, 16:33
    #39772373
Landgraf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
Ребята всем спасибо за ответы.
В итоге сделал так: Отобрал все необходимые партиций, сделал altet table truncate partition, а потом alter table drop partition.

После того, как удалил данные, теперь нужно уменьшить таблицу, скорректировать уровень HWM.
Я так понимаю можно сделать либо:

Код: plsql
1.
alter table shrink space


Либо
Код: plsql
1.
alter table move



Во втором варианте нужно будет ещё индексы перестроить и пересобрать статистику.

Какой вариант предпочтительней? Таблица весит около 400Гб, партицирована.

В оракловой доке написано, что shrink ужимает неиспользуемое пространство с низу и с верху HWM.
...
Рейтинг: 0 / 0
11.02.2019, 16:48
    #39772381
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
Landgrafнужно уменьшить таблицу, скорректировать уровень HWMHWM - это свойство сегмента, а не объекта.
...
Рейтинг: 0 / 0
11.02.2019, 16:53
    #39772386
Landgraf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
ElicLandgrafнужно уменьшить таблицу, скорректировать уровень HWMHWM - это свойство сегмента, а не объекта.

Да, есть такое.
...
Рейтинг: 0 / 0
11.02.2019, 17:15
    #39772406
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
andrey_anonymous,

drop partition update indexes не уменьшит число листьев индекса да и увеличит время выборки по глобальным индексам. UPDATE != REBUILD.

SY.
...
Рейтинг: 0 / 0
11.02.2019, 17:38
    #39772430
кит северных морей
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
LandgrafРебята всем спасибо за ответы.
В итоге сделал так: Отобрал все необходимые партиций, сделал altet table truncate partition, а потом alter table drop partition.

После того, как удалил данные, теперь нужно уменьшить таблицу, скорректировать уровень HWM.
Я так понимаю можно сделать либо:

Код: plsql
1.
alter table shrink space


Либо
Код: plsql
1.
alter table move



Во втором варианте нужно будет ещё индексы перестроить и пересобрать статистику.

Какой вариант предпочтительней? Таблица весит около 400Гб, партицирована.

В оракловой доке написано, что shrink ужимает неиспользуемое пространство с низу и с верху HWM. пересоберите global statistics и перестройте global indexes, если есть. больше ничего делать не нужно. truncate partition был лишним.
...
Рейтинг: 0 / 0
11.02.2019, 18:14
    #39772466
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
SYdrop partition update indexes не уменьшит число листьев индекса
Не уменьшит - в сравнении с ЧЕМ?
...
Рейтинг: 0 / 0
11.02.2019, 18:16
    #39772468
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
andrey_anonymousНе уменьшит - в сравнении с ЧЕМ?

C rebuild.

SY.
...
Рейтинг: 0 / 0
11.02.2019, 19:05
    #39772493
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
SYC rebuild.

В сравнении с rebuild глобального индекса по крупной таблице некоторое падение производительности и последующая подчистка orphanned ночным джобиком - сущая ерунда с точки зрения доступности системы.
...
Рейтинг: 0 / 0
11.02.2019, 20:08
    #39772503
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
andrey_anonymousпоследующая подчистка orphanned ночным джобиком

В смысле ночным index rebuild? Хорошо когда не 24x7 - у меня удаление soft deleted index keys получаетя только когда release. Проверить насколько дополнительный предикат проверки на orphaned влияет на производительность все руки не доходят.

SY.
...
Рейтинг: 0 / 0
12.02.2019, 14:35
    #39772852
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
SYandrey_anonymousпоследующая подчистка orphanned ночным джобиком
В смысле ночным index rebuild?
DBMS_PART.CLEANUP_GIDX
...
Рейтинг: 0 / 0
13.02.2019, 01:01
    #39773101
Fogel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
Коллеги, вы сильно усложняете всё.

Landgraf Ребята всем привет!

Нужен ваш совет.
Есть таблица размером в 800 Гб. Она партицирована по полю dDate (тип дата). Нужно удалить все записи у которых dDate < 01.01.17.

Учитывая размер таблицы, оператор delete будет работать очень долго.
Думал над таким вариантом:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
Create table MyTable_tmp as
select * from MyTable where dDate >= 01.01.17;

Truncate table MyTable;

Insert into mytable
Select * from mytable_p



Но при таком варианте пропадает партицирование.
Как бы сделать так, чтобы партицирование не слетели по оставшимся записям?

Будьте проще.

1. смОтрите скрипт создания вашей оригинальной таблицы (со всеми индексами, констрэйнтами и т.д.).
Копируете его целиком. (заменяете названия индексов и констрэйнтов, дописывая 1 в конце)
2. Вместо
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
create table MyTable
(col1,
col2,
...
colN)
tablespace <какое-то tb>
PARTITION BY RANGE (dDate)
...
и там потом индексы и прочие констрэйнты с комментариями


--
пишете
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
create table MyTable_NEW -- выкидываете весь блок столбцов здесь
tablespace <какое-то tb>
    PARTITION BY RANGE (dDate)
INTERVAL(NUMTOYMINTERVAL(1, 'DAY'))
( PARTITION p0 VALUES LESS THAN (TO_DATE('01-01-2017', 'DD-MM-YYYY')),
PARTITION p1 VALUES LESS THAN (TO_DATE('01-02-2017', 'DD-MM-YYYY'))
)
ENABLE ROW MOVEMENT
as select 
перечисление всех колонок, а не звёздочка
from MyTable
where dDate >= date '2017-01-01';
...
и там потом индексы и прочие констрэйнты с комментариями


3. собираете статистику
Код: plsql
1.
2.
3.
4.
5.
6.
begin
  dbms_stats.gather_table_stats(ownname     => <схема где таблица>,
                                tabname     => 'MYTABLE_NEW',
                                granularity => 'ALL',
                                force       => TRUE);
end;


4. Переименовываете таблички
Код: plsql
1.
2.
alter table MYTABLE rename to MYTABLE_OLD;
alter table MYTABLE_NEW rename to MYTABLE;


4.1 можете сверить данные в табличках всякими интерсектами и минусами для спокойствия души.

5.Дропаете старую таблицу с высвобождением места
Код: plsql
1.
drop table MYTABLE_OLD purge;


6. переименовываете все те индексы и констрэйнты, которым добавили 1 в пункте 1, обратно в оригинальные названия.
Код: plsql
1.
ALTER INDEX index1 RENAME TO oldnameindex; 


как-то так.
без лишней головной боли, с сохранением партиций и прочей структуры таблицы, корректным высвобождением места (без "хвостов" от шринкования ) и т. д., и т. п. ...
...
Рейтинг: 0 / 0
13.02.2019, 06:56
    #39773122
кит северных морей
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
FogelБудьте проще.
как говорила моя не по годам мудрая соседка по парте классе в шестом, "просто даже мухи не еб-ся".

2e12
...
Рейтинг: 0 / 0
13.02.2019, 21:50
    #39773609
flexgen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Удалить записи с сохранением партиций
FogelКоллеги, вы сильно усложняете всё...

Ты не упомянул о следующих шагах:
1. Не забыть дать все необходимые права на созданные заново таблицы поскольку при переименовании объекта теряются и права на него.
2. Проверить не стали ли объекты, каким-либо образом использующие пересоздаваемые таблицы, инвалидными и, соответственно, перекомпилировать эти объекты.
3. Не забыть про foreign key constraints в других таблицах, завязанные на пересоздаваемые таблицы.
4. И главное - без downtime, пусть даже минимального, все равно не обойтись.
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Удалить записи с сохранением партиций / 18 сообщений из 18, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]