Обновление NULL в sqlite происходит слишком медленно для большой базы данных - PullRequest
0 голосов
/ 07 февраля 2020

У меня есть таблица базы данных sqlite ~ 529M строк. Я выбрал sqlite, потому что не будет много записей в БД (только в основном для чтения), и я хотел, чтобы это было просто в одном файле. К сожалению, я допустил ошибку при создании базы данных: теперь мне нужно изменить некоторые значения NULL в двух столбцах посредством внутреннего соединения с другой таблицей.

Форматы таблиц:

>>> cdr
ego_id   alter_id   date        tower_id   city         state
123      456        20200101    98766      Los Angeles  California
789      143        20200105    09232      NULL         NULL
789      143        20200105    42106      NULL         NULL


>>> towermap
tower_id     city        state
98766        Los Angeles California
09232        Rochester   New York

что я хочу, чтобы значения NULL были отмечены в cdr и заменены на значения city,state в towermap, соответствующие tower_id. Результат должен быть:

>>> cdr
ego_id   alter_id   date        tower_id   city         state
123      456        20200101    98766      Los Angeles  California
789      143        20200105    09232      Rochester    New York
789      143        20200105    42106      NULL         NULL

Вот мой необработанный SQL, который я выполнил с помощью sqlalchemy (я использую Python). Кажется, sqlite не может выполнить ОБНОВЛЕНИЕ с ВНУТРЕННИМИ СОЕДИНЕНИЯМИ, поэтому я сделал следующий код после прочтения ответов в связанном вопросе .

q = """
UPDATE cdr                                                                                                                      
SET city = (SELECT city FROM towermap WHERE tower_id = cdr.tower_id),
      state=(SELECT state FROM towermap WHERE tower_id = cdr.tower_id)
WHERE (city IS NULL OR state IS NULL)
"""

engine = sqlalchemy.create_engine('sqlite:///my_file_loc.db')
conn = engine.connect()
conn.execute(q)
conn.close()

Я ожидаю, что ~ 35M строк будут иметь значение NULL значения, которые могут или не могут быть заменены (в зависимости от того, существует ли их tower_id в towermap). Уже прошло 18 часов, а db-journal продолжает расти. С памятью проблем нет.

Может ли мой код быть дополнительно оптимизирован для скорости? Возможно, я мог бы добавить что-то вроде PRAGMA synchronize = OFF;, но я бы избегал этого, если это возможно.

1 Ответ

1 голос
/ 07 февраля 2020

Вы можете обновить оба столбца одним подзапросом, используя значение строки примечание, уменьшив объем работы, которая должна быть выполнена в каждой соответствующей строке, наполовину:

UPDATE cdr                                                                                                                      
SET (city, state) = (SELECT city, state FROM towermap WHERE tower_id = cdr.tower_id)
WHERE (city IS NULL OR state IS NULL)

towermap.tower_id должен иметь индекс, если его еще нет (как если бы это был первичный ключ. Полные определения таблиц всегда лучше, чем просто список имен столбцов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...