Каков наилучший способ обновить (или заменить) всю таблицу базы данных на работающем компьютере? - PullRequest
7 голосов
/ 24 мая 2009

Мне еженедельно дают источник данных, который я собираюсь проанализировать и поместить в базу данных. Данные не будут сильно меняться от недели к неделе, но я должен обновлять базу данных на регулярной основе. Помимо этого еженедельного обновления данные статичны.

Пока восстановление всей базы данных не проблема, но в конечном итоге эта база данных станет активной, и люди могут запрашивать базу данных, пока я ее перестраиваю. Объем данных не мал (пара сотен мегабайт), поэтому он не загружается мгновенно, и лично я хочу немного больше надежной системы, чем «Я надеюсь, что никто не запрашивает, пока база данных находится в беспорядке».

Я думал о нескольких разных способах решения этой проблемы, и мне было интересно, каким будет лучший метод. Вот мои идеи на данный момент:

  1. Вместо замены целых таблиц, запросите разницу между моей текущей базой данных и тем, что я хочу поместить в базу данных. Похоже, что это может быть ненужный объем работы.

  2. Создание фиктивных таблиц данных, затем переименование таблицы (или указание кода сервера в направлении новых таблиц данных).

  3. Просто сообщите пользователям, что сайт проходит техническое обслуживание, и отключите систему на несколько минут. (Это не является предпочтительным по очевидным причинам, но если это лучший ответ, я готов это принять.)

Мысли

Ответы [ 6 ]

5 голосов
/ 24 мая 2009

Я не могу говорить за MySQL, но PostgreSQL имеет транзакционный DDL. Это замечательная функция, и это означает, что ваш второй вариант, загружая новые данные в фиктивную таблицу и затем выполняющий переименование таблицы, должен работать отлично. Если вы хотите заменить таблицу foo на foo_new, вам нужно только загрузить новые данные в foo_new и запустить скрипт для переименования. Этот сценарий должен выполняться в своей собственной транзакции, поэтому, если что-то не так с переименованием, и foo, и foo_new останутся нетронутыми при откате.

Основная проблема этого подхода заключается в том, что он может немного запутаться, обрабатывая внешние ключи из других таблиц, которые вводят foo. Но, по крайней мере, вы гарантировано, что ваши данные останутся непротиворечивыми.

Лучшим подходом в долгосрочной перспективе, я думаю, является просто непосредственное обновление данных (ваш первый вариант). Еще раз, вы можете закрепить все обновления в одной транзакции, так что вам гарантирована семантика "все или ничего". Еще лучше было бы онлайн обновления, просто обновляя данные непосредственно, когда новая информация становится доступной. Это может не подойти вам, если вам нужны результаты чьей-либо пакетной работы, но если вы можете это сделать, это лучший вариант.

3 голосов
/ 24 мая 2009
BEGIN;
DELETE FROM TABLE;
INSERT INTO TABLE;
COMMIT;

Пользователи увидят переход сразу же после того, как вы нажмете commit. Любые запросы, запущенные до фиксации, будут выполняться для старых данных, а все последующие будут выполняться для новых данных. База данных фактически очистит старую таблицу, как только последний пользователь покончит с ней. Поскольку все «статично» (вы единственный, кто изменяет его, и только раз в неделю), вам не нужно беспокоиться о каких-либо проблемах с блокировкой или тайм-аутах. Для MySQL это зависит от InnoDB. PostgreSQL делает это, а SQL Server называет это «моментальным снимком», и я не могу вспомнить подробности, потому что редко использую это.

Если вы Google "изолируете транзакцию" + имя какой-либо базы данных, которую вы используете, вы найдете соответствующую информацию.

2 голосов
/ 24 мая 2009

Мы решили эту проблему, используя механизм наследования / ограничения таблиц PostgreSQL. Вы создаете триггер, который автоматически создает вложенные таблицы, разделенные на основе поля даты.

Эта статья была источником, который я использовал.

1 голос
/ 24 мая 2009

Используйте разные имена таблиц (mytable_ [yyyy] _ [wk]) и представление для предоставления вам постоянного имени (mytable). Как только новая таблица будет полностью импортирована, обновите представление, чтобы оно использовало эту таблицу.

1 голос
/ 24 мая 2009

Несколько систем баз данных (поскольку вы не указали свою, я оставлю это общее) предлагают стандартное выражение SQL: 2003 под названием MERGE, которое в основном позволит вам

  • вставка новых строк в целевую таблицу из источника, которого там еще нет
  • обновить существующие строки в целевой таблице на основе новых значений из источника
  • при желании даже можно удалить строки из цели, которые больше не отображаются в таблице импорта

SQL Server 2008 является первым предложением Microsoft, имеющим это утверждение - узнайте больше здесь , здесь или здесь .

Вероятно, другие системы баз данных будут иметь аналогичные реализации - в конце концов, это стандарт SQL: 2003.

Марк

1 голос
/ 24 мая 2009

Какой сервер базы данных вы используете? SQL 2005 и выше предоставляет метод блокировки, называемый «Снимок». Он позволяет вам открыть транзакцию, выполнить все ваши обновления, а затем зафиксировать все, пока пользователи базы данных продолжают просматривать данные до транзакции. Обычно ваша транзакция блокирует ваши таблицы и блокирует их запросы, но в вашем случае идеально подойдет блокировка моментальных снимков.

Больше информации здесь: http://blogs.msdn.com/craigfr/archive/2007/05/16/serializable-vs-snapshot-isolation-level.aspx

Но для этого требуется SQL Server, поэтому, если вы используете что-то еще ....

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...