LINUX.ORG.RU

Медленный запрос к sqlite

 


0

2

Есть одна sqlite база в которой есть таблица

И есть запрос - посчитать сколько новых юзеров было за последнее время, тех у кого есть записи за последнее время но нет ранее

И уже сейчас когда записей всего 120т запрос выполняется несколько секунд блокируя всю базу. Как его можно ускорить?


CREATE TABLE IF NOT EXISTS msg_counter (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  user_id TEXT,
  access_time REAL,
  model_used TEXT
)

CREATE INDEX IF NOT EXISTS idx_access_time ON msg_counter (access_time)
CREATE INDEX IF NOT EXISTS idx_user_id ON msg_counter (user_id)
CREATE INDEX IF NOT EXISTS idx_model_used ON msg_counter (model_used)



SELECT COUNT(DISTINCT user_id)
  FROM msg_counter 
  WHERE access_time > ?
  AND NOT EXISTS (
    SELECT 1
    FROM msg_counter AS mc2
    WHERE mc2.user_id = msg_counter.user_id
    AND mc2.access_time <= ?
)

★★

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

theurs ★★
() автор топика

это же не проблема. секельлайт - это база для одного пользователя для простенького десктопного приложения. 2-3 секунды пользователь не заметит

rtxtxtrx ★★
()

Может тут вообще другой подход нужен. Сохранять в базе каждое сообщение с меткой времени ради того что бы можно было контролировать количество в единицу времени (например запрещать больше чем 1000 в неделю) это как от странно.

Кажется что можно сделать какой от хитрый счетчик для этого.

theurs ★★
() автор топика
Последнее исправление: theurs (всего исправлений: 1)
Ответ на: комментарий от TeopeTuK

И к такому ещё двухколоночный индекс по (user_id, access_time) чтоб ускорить внутренний запрос.

Два независимых одноколончных индекса к двухколоночному не имеют отношения.

GPFault ★★
()

Правильно ли я понял, что у вас 120 кило юзеров, и вы сидите в sqlite? Эта бд, немного для другого создавалась. Запрос нормальный, индексы тоже, ожидаю, что бд не хватает памяти, она начинает использовать диск из-за этого тормоза. Если не хотите ничего менять, то засуньте её всю в память - mode=memory. Если вся не помещается, то там много pragma настроек https://www.sqlite.org/pragma.html

Возможно оптимизатор надо подёргать https://www.sqlite.org/pragma.html#pragma_optimize

vtVitus ★★★★★
()
Последнее исправление: vtVitus (всего исправлений: 3)
Ответ на: комментарий от vtVitus

Не нужно тут никаких индексов. Нужен просто фулскан по таблице msg_counter, агрегация по user_id (жалкие 120 тысяч строк в памяти), фильтрация, подсчёт кол-ва строк.

iliyap ★★★★★
()

выше уже ответили как решить, добавлю что проблема в том что это не один запрос а 120к запросов (по запросу на каждую запись! даже не на юзера, а на каждую запись, причем каждый запрос проходится по всем записям относящимся к юзеру которому принадлежит запись, то есть сложность выполнения этого запроса - N^2, то есть 14 миллиардов операций)

ei-grad ★★★★★
()
Ответ на: комментарий от vtVitus

Правильно ли я понял, что у вас 120 кило юзеров

Нет юзеров не много. Это записи о каждом сообщении от юзеров.

Добавил в базу время первого появления юзеров отдельной строкой, теперь работает моментально.

theurs ★★
() автор топика