Медленное удаление SQLite

#performance #sqlite #sql-delete

#Производительность #sqlite #sql-delete

Вопрос:

У меня есть база данных SQLite (первый проект с SQLite), где мне нужно удалить сразу большую часть записей, это примерно 14 000 записей. Запрос выглядит следующим образом (я изменил имена для лучшего чтения) :

 delete from table_1 where table_2_id in (
    select id from table_2 where table_3_id in ( 
        select id from table_3
        where (deleted = 1 or
               table_4_id in (select id from table_4 where deleted = 1))));
  

Удаление этого запроса занимает около 8 минут. Но когда я делаю

 select * from table_1 where table_2_id in (
    select id from table_2 where table_3_id in ( 
        select id from table_3
        where (deleted = 1 or
               table_4_id in (select id from table_4 where deleted = 1))));
  

это дает мне результат за 3 секунды.

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

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

1. Создайте временную таблицу ( CREATE TEMP TABLE to_delete AS select table_1_id FROM table1 ... ); как быстро выполняется удаление с помощью этого ( delete from table_1 where table_1_id in to_delete )?

2. Спасибо за быстрый ответ. Для создания временной таблицы потребовалось менее секунды, поэтому кажется, что производительность правильная. Чтобы удалить конкретные данные с помощью запроса «удалить из таблицы_1, где table_1_id в (выберите идентификатор из to_delete)», это снова займет около 8 минут.

3. Насколько велик файл базы данных? Сколько у вас памяти? Какая файловая система? Сеть?

4. В настоящее время у меня есть следующие спецификации: Размер = 30 МБ, Память: 8 ГБ, диск: SSD, Система: Windows 7, Сеть: локальное хранилище

5. 30 МБ? Не ГБ? У вас есть сканер вирусов?

Ответ №1:

У меня была та же проблема. Решение состояло в том, чтобы разделить его на множество меньших фрагментов и делать это снова и снова, пока не будет затронуто больше строк (sqlite3_changes() возвращает ноль).

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

Ответ №2:

Это было 30 МБ, а также отключило сканер вирусов, но без какого-либо результата. Итак, я попробовал несколько способов, скопировал базу данных, удалил все внешние ключи и повторил попытку, и это было намного быстрее. Итак, затем я поместил индекс для всех внешних ключей, и он также быстро удалялся. Итак, это было решение, но я не знаю, почему оно затем выбирает fast и удаляет super slow. Но надеюсь, что это кому-нибудь поможет!

Ответ №3:

Есть ли у вас индекс для какого-либо из задействованных столбцов? Если это так, подумайте о том, чтобы удалить его для большого удаления, а затем перестроить его. Если вы этого не сделаете, попробуйте добавить его.

Ответ №4:

У меня есть скрипт на python для удаления записей в базе данных SQLite, lfl — это список файлов, которые я хочу удалить из базы данных, в заявлении значительно ускоряется процесс:

 while len(lfl)>0:
    print ("Deleting entries in DB: ",len(lfl))
    sql="""delete from md5t where file in ('%s')"""%('',''.join(tuple(lfl[:500])))
    cursor.execute(sql)
    db.commit()
    del lfl[:500]