Задать вопрос
tamaz1987
@tamaz1987
Умный, красивый

Долгая обработка SQL запроса?

Добрый день.
Изучаю python и работу с SQLite3.
Очень смущает долгая обработка запроса.
Имеем VPS сервер 1 ядро в 2.5 ГГЦ и оперативки в 2 ГБ.
SQLite3 база с двумя таблицами. Записей в одной 11 миллионо в другой 3 миллиона.
требования из первой таблицы удалить все значения которые есть во второй. Сверка по одному столбцу.
Код в python который это делает:
print('Запуск удаления проверенных юзеров')
    step = 0
    cur.execute('''SELECT user_full_data_user_id FROM user_full_data''')
    user_parsing_ok = cur.fetchall()
    korteg = ()
    for k in user_parsing_ok:
        korteg += k
        step += 1
    cur.execute(f'''DELETE FROM parsing
                    WHERE parsing_user_id IN {korteg}''')
    con.commit()
    cur.execute('''VACUUM''')  # Сжимаем таблицу удаляя пустые строки в ней
    print(f'Строк проверенно {step}')

Данный код на удаленной машине выполняется уже 10 часов и еще не завершился.
ПОчему так медленно. Это ограничания SQLite3, сам Python медленный или я написал кривой код?
  • Вопрос задан
  • 147 просмотров
Подписаться 1 Простой 7 комментариев
Решения вопроса 2
Lord_of_Rings
@Lord_of_Rings Куратор тега Python
Дунадан - северный странник. Злой, но очень добрый
Можно использовать подзапрос вместо двух запросов и цикла, если я не ошибаюсь
cur.execute('''DELETE FROM parsing
               WHERE parsing_user_id IN (SELECT user_full_data_user_id FROM user_full_data)''')
Ну и, конечно, sqlite - это не для таких БД

P. S. Можно ещё индексы сделать к столбцам
CREATE INDEX idx_user_full_data_user_id ON user_full_data(user_full_data_user_id);
CREATE INDEX idx_parsing_user_id ON parsing(parsing_user_id);
Ответ написан
Vindicar
@Vindicar
RTFM!
Какое лютое извращение.
user_parsing_ok = cur.fetchall()
    korteg = ()
    for k in user_parsing_ok:
        korteg += k
        step += 1

Во-первых, вы вытаскиваете 3 миллиона записей в память как питоновские объекты. Это не очень хорошая идея.
Во-вторых, вместо того, чтобы по-человечески сделать
korteg = tuple(item[0] for item in user_parsing_ok)
вы делаете конкатенацию кортежей по одному. Напомню, что при конкатенации создаётся новый кортеж - так что при добавлении трёхмиллионного элемента у вас в памяти будет один кортеж с 2999999 элементами и один кортеж с 3000000 элементами. Это дело будет люто, бешено, неиллюзорно жрать память, а значит, свопиться на диск. Что не прибавит скорости.
Как написали выше, просто используйте подзапрос. Вам совершенно незачем таскать эти айдишники из БД в питон, а потом из питона в БД. Пусть они обрабатываются только в рамках БД.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы