|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Доброго времени суток. Столкнулся с проблемой переноса данных в историческую базу. Задача. имеем таблицу с 300 миллионами+ записями есть два поля, год и квартал, по которым можно определить что вырезаем, а что оставляем. Фактически 2/3 данных нужно перенести в другую таблицу и удалить в первоначальной. ddl таблицы которая требует обрезки create table dbo.tbl_store ( id numeric(18, 0) identity, year_ smallint not null, qq_ tinyint not null, member_id numeric(18, 0) not null, complect_code varchar(20) not null, chances decimal(14, 10) not null, state tinyint DEFAULT 0 not null, num smallint not null, shop_del tinyint null, constraint PKtbl_store_id PRIMARY KEY NONCLUSTERED ( id ) ) lock datarows on 'default' go print 'XXmembID' create nonclustered index XXmembID on dbo.tbl_store (member_id) on 'default' print 'XXmemb_num_state' create nonclustered index XXmemb_num_state on dbo.tbl_store (member_id, num, state) on 'default' Индексы строить не вариант на полях year_ и qq_, так как происходит залочка и вообщем пользователи плачут. Программисту который такое сваял, тоже уже ничего не поможет. Пробовал вариант с временной таблицей. Создаю временную таблицу, ставлю SET rowcount 100 после чего закидываю в нее данные из родительской. Данные в таблице находятся по порядку. То есть самые старые в начале и тд. Затем полученные данные из времянки. по условию к примеру, 2012 год и 2 квартал, делаю инсерт в историческую базу в таблицу. после этого удаляю из родительской. Код: sql 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.
Проблема в том что все это ну очень долго происходит, и к примеру за один квартал - это 30 лямов, выгружается около 10%, после чего закачивается место в tempdb. Запускаю через *.bat isql. Гуру подскажите плиз какие есть варианты решения проблемы? Adaptive Server Enterprise/12.5.4/EBF 16791 ESD#10/P/NT (IX86)/OS 4.0/ase1254/2159/32-bit/OPT/Mon Nov 02 05:01:55 2009 ... |
|||
:
Нравится:
Не нравится:
|
|||
19.01.2015, 15:55 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88, Задачка тривиальная, несколько вариантов решения может быть. Из быстрых: 1) создать view1 для исторических данных 2) выгрузить её (select ... from view1) в файл1 с помощью BCP 3) создать view2 для данных, которые должны остаться в исходной таблице 4) выгрузить её (select ... from view2) в файл2 с помощью BCP 5) truncate исходной таблицы 6) удалить на ней индексы 7) залить в нее файл2 с помощью BCP 8) построить индексы обратно 9) в историческую таблицу залить файл1 с помощью BCP, удалив индексы и создав их обратно после заливки предварительно почитать про режимы BCP : http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc30191.1550/html/utility/X20696.htm ... |
|||
:
Нравится:
Не нравится:
|
|||
19.01.2015, 18:53 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Предложение хорошее, в бытность работы с MS SQL Server я бы так и поступил, но тут меня смущает процесс постоения индексов на таблице со 100 миллионами записей. Сколько это будет по времени, и будут же залочки во время создания индексов, и пользователи жаловаться будут. А окна технологического нету :(. Но я все же попробую в тестовой среде предложенный Вами вариант. Спасибо. А какие есть еще варианты ? ... |
|||
:
Нравится:
Не нравится:
|
|||
19.01.2015, 22:10 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88Предложение хорошее, в бытность работы с MS SQL Server я бы так и поступил, но тут меня смущает процесс постоения индексов на таблице со 100 миллионами записей. Сколько это будет по времени, и будут же залочки во время создания индексов, и пользователи жаловаться будут. А окна технологического нету :(. Но я все же попробую в тестовой среде предложенный Вами вариант. Спасибо. А какие есть еще варианты ? На вскидку, разной степени простоты и трудозатратности: * Базу в режим truncate log on checkpoint, удалять батчами. * Создать рядом вторую таблицу, перелить туда нужные данные, построить индексы, после этого переименовать объекты - старую таблицу и новую поменять местами; провести рекомпиляцию связанных объектов; из переименованной перелить исторические данные в историческую таблицу. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2015, 01:18 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88Предложение хорошее, в бытность работы с MS SQL Server я бы так и поступил, но тут меня смущает процесс постоения индексов на таблице со 100 миллионами записей. Сколько это будет по времени, и будут же залочки во время создания индексов, и пользователи жаловаться будут. А окна технологического нету :(. Но я все же попробую в тестовой среде предложенный Вами вариант. Спасибо. А какие есть еще варианты ? Привет! Все варианты, которые подразумевают прозрачный для пользователей перенос будут длительны во времени. Поправим немного план komrad'a, тем более что во втором посте он намекает... 1) создать view1 для исторических данных 2) выгрузить её (select ... from view1) в файл1 с помощью BCP 3) в историческую таблицу залить файл1 с помощью BCP, удалив индексы и создав их обратно после заливки 4) Выбрать время минимальной загрузки (ночь, ранее утро etc) и удалять исторические данные конструкцией delete top 10000 from... в while (@@rowcount != 0) Да, это займет время, но прозрачно для пользователей. (не забудь включить обрезание лога по чекпоинту в базе) ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2015, 14:40 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
SQLMantisПривет! Все варианты, которые подразумевают прозрачный для пользователей перенос будут длительны во времени. Поправим немного план komrad'a... с корректировкой согласен, тем более что мой вариант был схематичным SQLMantisДа, это займет время, но прозрачно для пользователей. (не забудь включить обрезание лога по чекпоинту в базе) решение об автоматическом обрезании лога на продакшен базе требует некоторого размышления от автора "только трусы делают дампы" (с) начальник ;) ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2015, 22:27 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Спасибо друзья за советы! Буду осуществлять на практике! ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2015, 09:14 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88, Код: sql 1.
Логично предположить, что дата у вас линейно зависима на Id , т.е. чем больше Id тем больше дата и не может быть двух записей с ID1 > ID2 , в которых Date2 < Date1 . По Id есть индекс. Задача сводится к удалению по ID . Делаете процедуру (без представлений и пр.), которая: 1. Копирует батч (X записей) в архивную таблицу по диапазону ID: ID between N1 and N2 , при этом ID < MaxID (само собой количество записей между N1 и N2 должно быть больше либо равно X для снижения количества иттераций) . Где MaxId соответствует идентификатору записи с максимальной датой, которую можно удалить - найти этот MaxId думаю не составит труда для вас. Архивная таблица имеет признак на каждой записи, типа HaveDeleted / WhenDeleted с индексом по этому полю. При копировании, поле равно 0. 2. Батчем удаляете записи из основной, у которых ID соответствует записям из архивной с признаком HaveDeleted = 0 . 3. Апдейтите архивную: записи с HaveDeleted = 0 на HaveDeleted = 1 если соответствующий ID не найден в основной таблице. С виду монстрообразная конструкция, не самая оптимальная по быстродействию, но позволит: а) переносить данные в архив мелкими партиями по Х записей - не блокирую других пользователей. б) удалять данные из основной таблицы партиями по Х1 записей (при этом Х <> Х1), опять же не блокируя пользователей и обеспечивая приемлемую нагрузку на сервер/лог/таблицу, учитывая все особенности вашей системы. в) "развести" процесс копирования и удаления по времени, тем самым "разгрузив" систему. К примеру, копирование может быть "грязным" и вообще без локов (старые данные же у вас не меняются? Так ведь?). Удаление можно проводить в периоды низкой нагрузки системы, вплоть до одной записи. г) обеспечить целостность данных - ничего не теряете в итоге. д) растянуть процесс во времени, если система 24х7 - нет необходимости в простое. При желании копирование и удаление могут быть разведены по двум независимым процессам - но тут надо аккуратно подходить - дабы процессы друг друга не блокировали. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2015, 11:01 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Mikle83, похоже воспользуюсь именно вашим советом, так как вариант с bcp отпадает, так как база куда будут помещены исторические данные, находится под репликацией и разрешено только bcp-выкачка данных. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2015, 11:48 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88Mikle83, похоже воспользуюсь именно вашим советом, так как вариант с bcp отпадает, так как база куда будут помещены исторические данные, находится под репликацией и разрешено только bcp-выкачка данных. Тут давайте остановимся, посчитаем до 10 и Вы нам расскажите по подробнее про "база находится под репликацией" ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2015, 12:08 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
SQLMantis, Подробнее, есть два сервера БД, издатель и подписчик. 4 базы на каждом, все они под репликацией. Какие вопросики будут ? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2015, 12:28 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88SQLMantis, Какие вопросики будут ? Как реализована репликация? Какими средствами? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2015, 15:14 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
SQLMantis, настроен RS 15.7 ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2015, 16:46 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88SQLMantis, настроен RS 15.7 Круто :) warm standby? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2015, 16:59 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
SQLMantis, простите? Я только несколько месяцев работаю с данной БД и репликатором. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2015, 17:56 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
SQLMantis, простите? Я только несколько месяцев работаю с данной БД и репликатором. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2015, 09:59 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88SQLMantis, простите? Я только несколько месяцев работаю с данной БД и репликатором. Тогда, пока ничего не трогайте. А то мы тут насоветовали много такого от чего переполняются logsegment'ы и пухнут очереди в RS. Перво наперво нужно узнать участвует ли ваша таблица в репликации. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2015, 14:23 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
SQLMantiskostik88SQLMantis, простите? Я только несколько месяцев работаю с данной БД и репликатором. Тогда, пока ничего не трогайте. А то мы тут насоветовали много такого от чего переполняются logsegment'ы и пухнут очереди в RS. Перво наперво нужно узнать участвует ли ваша таблица в репликации. Ну вот. И так в топике про Sybase - скучно, так еще и потенциальную тему "упала репликация" - срубили :( По теме - если есть репликация => +1 к варианту с процедурой. В начале указать отключение репликации на сессию. Запуск раздельный на primary и на подписчике(ах). Возможна рассинхронизация данных между архивными таблицами и "архивных" данных в основной, но, скорее всего, это не критично для бизнес задач - надо уточнять у ваших аналитиков/бизнеса. В любом случае, никто не мешает собрать представление с UNION обоих таблиц и завязать всю отчетность на представление, если это реально критично. Можно и не тушить репликацию, как раз за счет батчей снизить нагрузку, обернуть все в отдельные транзакции... Но есть предположение, что нет у вас полноценного тестового сервера с настроенной репликацией, что не позволит полноценно отладить процессы до внедрения схемы в прод. P.S.: на архивируемую таблицу другие не ссылаются случаем? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2015, 15:40 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Спасибо всем кто откинулся на мой вопрос! На счет репликации, под ней все и таблицы и прочие объекты и тд. Таблица которую буду "резать", так же под репликацией, но она статична до порезки, и в нее на момент порезки никто добавлять ничего не будет. Просто нужно что бы в этой таблице был некий период, а остальное в хистори-базу. Так что тут все ок. На счет отключения репликации. Планирую обернуть процедуру через sp_setrepproc Оформил я так как предложил Mikle83, завернул в процедуру. Процедура Код: sql 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2015, 17:13 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88, Код: sql 1. 2.
странно это... Реально есть уверенность, что у вас нет "пропусков" в идентификаторах? Я делал что-то типа (с точностью до синтаксиса) Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Такой подход позволял нивелировать "пропуски" в идентификаторах и переносить в каждой иттерации +/- одинаковое количество записей, делая процесс более предсказуемым. c DELETE рисковано, на мой взгляд делать так: Код: sql 1. 2. 3. 4.
Я бы удалял то, что гарантированно перенесено в архив Код: sql 1. 2. 3.
Опять же, структура HasDeleted может оказаться полезной, если объем удаляемых записей не совпадает с объемом выборки на копирование. Если в вашем случае возможен вырожденный случай и эти два объема идентичны - крупно повезло, можно оставить и так... ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2015, 17:36 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Mikle83, Код: sql 1. 2.
поставил только для той ситуации, если случайно будет запущенно дважды. Плохой вариант ? На счет остальных подсказок, еще раз сенкс. Покручу с их учетом. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2015, 17:59 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Mikle83 В начале указать отключение репликации на сессию. Хмм. Можно поподробнее, что предлагается сделать? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2015, 18:09 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
SQLMantisMikle83 В начале указать отключение репликации на сессию. Хмм. Можно поподробнее, что предлагается сделать? к примеру следующий запрос в начале процедуры: Код: sql 1. 2.
все что будет "твориться" внутри процедуры не пойдет на реплику. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 11:00 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88поставил только для той ситуации, если случайно будет запущенно дважды. Плохой вариант ? Смотря как будете Min/Max определять для передачи в процедуру. по мимо варианта повторного запуска, возможно (особенно при последовательном переборе значений ИД), что наткнетесь на иинтервал [Min;Max] в котором нет записей. Процедура отработает с ексепшеном. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 11:03 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Mikle83, на счет удаления данных, я же беру некоторое количество записей, копирую их в хистори таблицу, и тут же по этому же диапазону произвожу удаление данных. Далее, изменение структуры таблицы увы не допустимо. Это на счет флага для скопированных записей. На счет отключения репликации, а это процедура sp_setrepproc разве не сделает то же самое? То есть я оберну выполнение своей процедуры через эту функцию, и отдельно запущу на издателе и подписчике. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 12:23 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88Mikle83, на счет удаления данных, я же беру некоторое количество записей, копирую их в хистори таблицу, и тут же по этому же диапазону произвожу удаление данных. Далее, изменение структуры таблицы увы не допустимо. Это на счет флага для скопированных записей. так менять структуру основной таблицы не надо. Флаг добавляется в архивную таблицу. Алгоритм: 1. копируем данные из основной в архивную (флаг HasDeleted = 0 ) 2. удаляем записи из основной, которые есть в архивной с флагом HasDeleted = 0 3. обновляем записи в архивной: если HasDeleted = 0 и запись отсутствует в основной - ставим флагу значение 1. Основная мысль - развести потоки копирования и удаления по разным процессам. В вашем случае вполне вероятно это не потребуется. kostik88На счет отключения репликации, а это процедура sp_setrepproc разве не сделает то же самое? То есть я оберну выполнение своей процедуры через эту функцию, и отдельно запущу на издателе и подписчике. Как вариант, можно через нее. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 12:27 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Mikle83, Спасибо за консультации! Вот еще бы динамически вычислять max(id) для конца периода, а то руками в несколько приемов приходится делать :). ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 12:43 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Деление на 10 делается для получения 1? ну то есть при @BatchSize = 100 ? Шаг единиуа. Правильно я понял ? ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 13:50 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88Деление на 10 делается для получения 1? ну то есть при @BatchSize = 100 ? Шаг единиуа. Правильно я понял ? Шаг 10 при BacthSize = 100. Принцип - да, правильно. Дабы не взять сразу 2 или 3 "разовых" объема записей - увеличиваем диапазон по не много, пока не наберем +/- нужное количество записей. Т.е. по факту у вас может быть количество записей от 100% до 110% от BatchSize. Если критичен такой объем и надо более точно "отмерять" = можно сделать "шаг" по 1%, по 0.5%. 10% для меня было оптимальным соотношением между "стабильностью" количества данных в каждом батче и количеством иттераций на поиск диапазона. P.S.: кстати, в итоге делал более продвинутый (но и более сложный) вариант этого механизма: если диапазон MinId MaxId не содержал нужного количества записей, то инкремент делался не последовательно а через алгоритм а) найти минимальный ID, который больше MaxId б) установить MaxId = найденный ID в пункте а) + (BatchSize - count_в_текущем_диапазоне). Еще меньше иттераций на поиск. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 14:01 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Вообщем, вот такой зверек получился :) Код: sql 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.
Так теперь же нужно его поводок сделать, то есть, как то ограничение сделать, что бы можно было в любое время после запуска, остановить. а как ? не лепить же цикл сверху существующего цикла ? ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 15:51 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
kostik88, оч просто перед циклом объявляете переменную, даже две Код: sql 1. 2.
Ну и в условие while- цикла добавляете что-то типа: Код: sql 1.
с точностью до синтаксиса ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 16:14 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Код: sql 1.
а это с какой целью добавлено? про остановить в любое (вообще любое) время - можно делать "остановку" через служебную таблицу, типа Код: sql 1.
так же в цикл while добивается условие Код: sql 1.
Т.е. как только в таблице появится запись для вашего процесса со статусом = 1 - выполнение процедуры прервется на ближайшем шаге цикла. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 16:57 |
|
Удаление из большой таблицы. Как?
|
|||
---|---|---|---|
#18+
Mikle83, Вариант супер, спасибо в очередной раз, и еще уточнить хотел, у меня инсерт и делит обернуты в транзакцию, в теории это должно помочь в ситуации когда мне может потребоваться остановить процесс, кильнуть процесс. В таком случае транзакция если была в процесс откатится ? ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2015, 17:06 |
|
|
start [/forum/topic.php?all=1&fid=55&tid=2009784]: |
0ms |
get settings: |
10ms |
get forum list: |
16ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
145ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
69ms |
get tp. blocked users: |
2ms |
others: | 15ms |
total: | 280ms |
0 / 0 |