медленная вставка и извлечение базы данных tcl

#sqlite #tcl

#sqlite #tcl

Вопрос:

Я новичок в tcl. Я подключился к базе данных SQLite.

У меня есть около 100 000 записей, которые я хочу вставить в базу данных после вычисления. Я использую следующую команду для вставки записей в базу данных 100 000 раз.

Я уверен, что здесь я делаю что-то не так. Какой был бы подходящий способ сделать это?

Для вставки:

 db eval {insert into table values(value1,value2,value3,value4)} 
  

Для извлечения мне приходится выполнять операцию выбора не менее 1000 раз, все происходит ужасно медленно:

 db eval {select x as x, y as y from table} {
   set z  [expr $z   $x   $y]
}
  

Комментарии:

1. Вы помещаете db eval {select ...} {...} в цикл, или в результате просто обрабатывается тысяча строк?

Ответ №1:

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

 db eval { BEGIN TRANSACTION }

... do some insertions ...

db eval {  END TRANSACTION }
  

или

 db transaction {

... do some insertions ...

}
  

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

В частности:

  • Отключить синхронизацию (PRAGMA synchronous = ВЫКЛ.;)
  • Групповая запись в транзакции
  • Индексные таблицы
  • Использовать базу данных в памяти

Если вы не изучили все это, то, скорее всего, работаете во много раз медленнее, чем могли бы.

Комментарии:

1. Это хорошо работает для вставок. Есть ли способ ускорить выбор?

2. В общем, выбор выполняется быстро, что означает меньшую возможность их оптимизации. Вы просмотрели ответ, на который я ссылался? Следующее, что нужно попробовать, это отключить синхронизацию. Но я подозреваю, что это не улучшит выбор.

3. Я просмотрел образец инструкции select, который вы опубликовали. Вы уверены, что узкое место находится в sqlite? Сколько времени требуется TCL для выполнения 1000 раз set z [выражение $ z $ x $ y]?

4. Фактически, открытие файла соответствует созданию соединения (т.е. db дескриптору). Тем не менее, транзакции по-прежнему дороги; запуск одной из них в значительной степени эквивалентен блокировке области файла, а ее фиксация соответствует, среди прочего, полной загрузке на диск. Очень дорого! Вывод базы данных из режима автоматической фиксации по умолчанию — огромная победа.

5. Интерфейс SQLite от Tcl имеет дополнительную бонусную функцию: поддержку синтаксических транзакций. Используйте следующим образом: db transaction { ... do some insertions ...} . Успешное завершение кода приводит к фиксации, генерируемые исключения приводят к откату. Просто.

Ответ №2:

Я не могу ответить на часть вопроса sqlite, потому что я не использовал sqlite несколько лет, но одной из причин снижения производительности является ваше выражение expr. Вам нужно заключить аргументы в скобки для выражения, что должно значительно ускорить эту часть вашего цикла:

 set z [expr {$z   $x   $y}]
  

Ответ №3:

Да, выполнение одиночных вставок из Tcl в таблицу sql — не самый быстрый способ выполнить то, что вы хотите.

Чтобы ускорить процесс, вы должны записать нужную таблицу во внешний файл и загрузить данные с помощью одной инструкции db.

Вы бы записали данные следующим образом:

 set fh [open temp_file w]
set rowid 0
# loop
  puts $fh [join [list $value1 $value2 $value3 $value4] t]
# end loop
close $fh
  

Затем, используя метод копирования, вы можете прочитать все за один раз:

 db copy replace values temp_file
  

А что касается вычисления суммы, я не знаю, почему вы не используете сам sql для выполнения суммирования. В Интернете есть много примеров того, как это сделать. Вот пара примеров. Я полагаю, что ваш оператор sql будет выглядеть примерно так:

 db select sum(x y) from table
  

или, возможно

 db select sum(x y) as z from table
  

Комментарии:

1. Я должен использовать некоторые значения, которые я вычисляю в программе, также со значениями, которые я получаю из таблицы.