Sqlite3: Отключить индекс первичного ключа при вставке? - PullRequest
13 голосов
/ 25 апреля 2009

У меня есть база данных Sqlite3 с таблицей и первичным ключом, состоящим из двух целых чисел, и я пытаюсь вставить в нее много данных (т. Е. Около 1 ГБ или около того)

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

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

Мой второй лучший план - создание прозрачных копий базы данных на сетевом диске, внесение изменений и последующее объединение. Обратите внимание, что в отличие от большинства вопросов по SQlite / NFS, мне не нужен параллелизм доступа.

Как правильно сделать что-то подобное?

UPDATE:

Я забыл указать флаги, которые я уже использую:

PRAGMA synchronous = OFF
PRAGMA journal_mode = OFF
PRAGMA locking_mode = EXCLUSIVE
PRAGMA temp_store = MEMORY

ОБНОВЛЕНИЕ 2: Фактически я вставляю элементы в пакеты, однако каждый следующий пакет фиксируется медленнее, чем предыдущий (я предполагаю, что это связано с размером индекса). Я попытался создать пакеты по 10–50 тыс., Каждая из которых состоит из двух целых чисел и числа с плавающей запятой.

Ответы [ 3 ]

11 голосов
/ 26 апреля 2009
  1. Вы не можете удалить встроенный индекс, так как это единственный адрес строки.
  2. Объедините ваши 2 целочисленных ключа в один длинный ключ = (key1 << 32) + key2; и сделать это как INTEGER PRIMARY KEY в схеме youd (в этом случае у вас будет только 1 индекс) </li>
  3. Установить размер страницы для новой БД не менее 4096
  4. Удалить ЛЮБОЙ дополнительный индекс, кроме основного
  5. Заполните данные в порядке SORTED, чтобы первичный ключ увеличивался.
  6. Повторно использовать команды, не создавайте их каждый раз из строки
  7. Установите размер кэша страницы равным количеству оставшейся памяти (помните, что размер кэша указывается в количестве страниц, а не в байтах)
  8. Зафиксировать каждые 50000 предметов.
  9. Если у вас есть дополнительные индексы - создавайте их только ПОСЛЕ ВСЕХ данных в таблице

Если вам удастся объединить ключ (я думаю, что вы используете 32-битный, а sqlite - 64-битный, так что это возможно) и заполнить данные в отсортированном порядке, держу пари, вы заполните свой первый Gb с той же производительностью, что и второй и оба будут достаточно быстрыми.

6 голосов
/ 25 апреля 2009

Вы делаете INSERT каждого нового как отдельную транзакцию?

Если вы используете BEGIN TRANSACTION и INSERT строк в пакетах, то я думаю, что индекс будет восстановлен только в конце каждой транзакции.

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