Sqlite3: Отключение индекса первичного ключа при вставке?
У меня есть база данных Sqlite3 с таблицей и основным ключом, состоящим из двух целых чисел, и я пытаюсь вставить в нее много данных (т.е. около 1 ГБ или около того)
Проблема, с которой я сталкиваюсь, заключается в том, что создание первичного ключа также неявно создает индекс, который в моем случае приводит в заблуждение вставки в обход после нескольких коммитов (и это связано с тем, что файл базы данных находится на NFS.. sigh),
Итак, я бы хотел как-то временно отключить этот индекс. Мой лучший план до сих пор включал в себя отказ от автоматического индекса первичного ключа, однако кажется, что SQLite ему не нравится и выдает ошибку, если я попытаюсь это сделать.
Мой второй лучший план будет включать приложение, делающее прозрачные копии базы данных на сетевом диске, внося изменения, а затем объединяя их. Обратите внимание, что в отличие от большинства вопросов SQlite/NFS мне не нужен доступ concurrency.
Каким будет правильный способ сделать что-то подобное?
UPDATE:
Я забыл указать флаги, которые уже использую:
PRAGMA synchronous = OFF
PRAGMA journal_mode = OFF
PRAGMA locking_mode = EXCLUSIVE
PRAGMA temp_store = MEMORY
ОБНОВЛЕНИЕ 2:
Я фактически вставляю элементы в партии, однако каждая следующая партия медленнее, чем предыдущая (я предполагаю, что это связано с размером индекса). Я пробовал делать партии между кортежами 10k и 50k, каждый из которых представляет собой два целых числа и float.
Ответы
Ответ 1
- Вы не можете удалить встроенный индекс, поскольку он является единственным адресом строки.
- Объединить 2 целых ключа в один длинный ключ = (key1 < 32) + key2; и сделайте это как ОСНОВНЫЙ КЛЮЧ INTEGER в схеме youd (в этом случае у вас будет только 1 индекс)
- Установить размер страницы для новой БД не менее 4096
- Удалить любой дополнительный индекс, кроме первичного
- Заполните данные в порядке SORTED, чтобы увеличить первичный ключ.
- Команды повторного использования, не создавайте каждый раз из строки
- Установите размер кеша страниц на столько же памяти, сколько и осталось (помните, что размер кеша находится в количестве страниц, но не в байтах)
- Зафиксируйте каждые 50000 элементов.
- Если у вас есть дополнительные индексы - создайте их только ПОСЛЕ ВСЕХ данных в таблице
Если вы сможете объединить ключ (я думаю, вы используете 32-битный, тогда как sqlite с 64-разрядным, так что это возможно) и заполнять данные в отсортированном порядке. Ставлю, вы заполните свой первый Gb той же производительностью, что и второй, и оба будут достаточно быстрыми.
Ответ 2
Вы делаете INSERT
каждого нового как отдельную транзакцию?
Если вы используете BEGIN TRANSACTION
и INSERT
строки в партиях, я думаю, что индекс будет восстановлен только в конце каждой транзакции.
Ответ 3
См. faster-bulk-inserts-in-sqlite3.