Я полагаю, что медлительность действительно заключается в построении индекса, поскольку все больше и больше записей добавляется. В зависимости от имеющейся у вас оперативной памяти, вы можете указать sqlite использовать достаточно памяти, чтобы вся эта деятельность по созданию индекса выполнялась в памяти (то есть без всех операций ввода-вывода, которые могли бы произойти в противном случае с меньшим объемом памяти).
Для 15M записей я бы сказал, что вы должны установить размер кэша на 500000.
Вы также можете указать sqlite хранить журнал транзакций в памяти.
Наконец, вы можете установить синхронное на ВЫКЛ, чтобы sqlite никогда не дожидалась записи на диск.
Используя это, я смог разделить время, необходимое для импорта 15M записей на 5 (14 минут до 2,5) с записями из случайных GUID, разделенных на 5 столбцов, используя три средних столбца в качестве индекса:
b40c1c2f 912c 46c7 b7a0 3a7d8da724c1
9c1cdf2e e2bc 4c60 b29d e0a390abfd26
b9691a9b b0db 4f33 a066 43cb4f7cf873
01a360aa 9e2e 4643 ba1f 2aae3fd013a6
f1391f8b f32c 45f0 b137 b99e6c299528
Поэтому, чтобы попробовать это, я предлагаю вам поместить все инструкции в некоторый файл, скажем import_test:
pragma journal_mode=memory;
pragma synchronous=0;
pragma cache_size=500000;
.mode tabs
.import variations_build_36_ens-54.tab ensembl_vf_b36
Тогда попробуйте:
time sqlite3 test_import.db < import_test
EDIT
Это ответ на комментарии Пабло (ОП), следующий за этим ответом (его долго не помещать в качестве комментария):
Мои (образованные) догадки таковы:
- Потому что .import не является sql как таковым,
это не так уж много шума с
транзакции, я даже склонен к
думаю, что написано идти
быстрее, чем если бы у вас было все это
сделано за одну "нормальную" транзакцию;
и
- Если у вас достаточно памяти для
выделить, и вы создали свой
среда, как я предполагаю, реальная
(время) боров здесь читает квартиру
файл, затем запись окончательного содержания
базы данных, потому что
случается между случается чрезвычайно
быстро; то есть достаточно быстро, что там
не так много времени, чтобы оптимизировать его
когда вы сравниваете такой потенциал
выигрывает с (вероятно) несжимаемым временем, затрачиваемым на дисковый ввод-вывод.
Если я ошибаюсь, я был бы рад услышать почему в свою пользу.
РЕДАКТИРОВАТЬ 2
Я провел сравнительный тест между наличием индекса во время .import и его добавлением сразу после завершения .import. Я использовал ту же технику генерации 15M записи из разделенных случайных UUID:
import csv, uuid
w = csv.writer(open('bla.tab', 'wb'), dialect='excel-tab')
for i in xrange(15000000):
w.writerow(str(uuid.uuid4()).split('-'))
Затем я протестировал импорт с индексом, созданным до и после (здесь индекс создается после):
pragma journal_mode=memory;
pragma synchronous=0;
pragma cache_size=500000;
create table test (f1 text, f2 text, f3 text, f4 text, f5 text);
CREATE INDEX test_idx on test (f2, f3, f4);
.mode tabs
.import bla.tab test
Так вот время добавления индекса до :
[someone@somewhere ~]$ time sqlite3 test_speed.sqlite < import_test
memory
real 2m58.839s
user 2m21.411s
sys 0m6.086s
А при добавлении индекса после :
[someone@somewhere ~]$ time sqlite3 test_speed.sqlite < import_test
memory
real 2m19.261s
user 2m12.531s
sys 0m4.403s
Вы видите, как разница времени пользователя (~ 9 с) не учитывает разницу полного времени (~ 40 с)? Для меня это означает, что при создании индекса ранее происходил некоторый дополнительный ввод-вывод, и поэтому я ошибался, полагая, что все выполняется в памяти без дополнительных операций ввода-вывода.
Вывод: создайте индекс после, и у вас будет еще лучшее время импорта (как упоминал Донал).