powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / SQLite [игнор отключен] [закрыт для гостей] / По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
6 сообщений из 6, страница 1 из 1
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
    #38687664
Dmitro25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте.
На базе в несколько сотен миллионов записей выполняется удаление устаревших записей.
При этом просто удаление
Код: sql
1.
DELETE FROM Data WHERE DateTime<%d;


не работает (программа, выполняющая запрос, в процессе запроса начинает занимать всю доступную память, и запрос прерывается с ошибкой "Out of memory").
В результате было решено удалять частями:
Код: sql
1.
DELETE FROM Data WHERE ID in (SELECT ID FROM Data WHERE DateTime<%d LIMIT 10000000);


данный запрос повторяется до тех пор, пока возвращённое функцией SQLite3_Changes() количество затронутых запросом записей не станет меньше 10000000.
Однако, наблюдается странная ситуация: первый же запрос на удаление возвращает не 10000000, а 9999998 затронутых запросом записей, и, в результате, дальнейшие запросы не производятся.
Количество записей в базе, которые удовлетворяют условию запроса, значительно больше 10000000.
Мало того, если я вручную снова запускаю процедуру удаления, снова возвращается то же число 9999998 затронутых записей.
Подскажите, по какой причине такое может получаться?
...
Рейтинг: 0 / 0
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
    #38688453
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dmitro25Здравствуйте.
На базе в несколько сотен миллионов записей выполняется удаление устаревших записей.
При этом просто удаление
Код: sql
1.
DELETE FROM Data WHERE DateTime<%d;


не работает (программа, выполняющая запрос, в процессе запроса начинает занимать всю доступную память, и запрос прерывается с ошибкой "Out of memory").А ты уверен что DateTime хранит данные в том же самом формате в котором ты константу отдаешь?

Показывай полный исходник и пример данных. Заодно уточни версию движка.



Dmitro25В результате было решено удалять частями:
Код: sql
1.
DELETE FROM Data WHERE ID in (SELECT ID FROM Data WHERE DateTime<%d LIMIT 10000000);

В морг. Кривое решение, могущее принести в миллионы раз больше проблем.
...
Рейтинг: 0 / 0
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
    #38689547
Dmitro25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl
Вот формат таблицы для хранения данных
Код: sql
1.
2.
3.
CREATE TABLE Data (ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, BlN INTEGER, Type INTEGER[1], DateTime INTEGER, 
Long INTEGER, Lat INTEGER, Speed INTEGER, Heading INTEGER[2], Alt INTEGER, GPSQty INTEGER);
CREATE INDEX i_datetime_bln on data (bln,datetime);


Вот точный sql-запрос на удаление
Код: sql
1.
DELETE FROM Data WHERE ID in (SELECT ID FROM Data WHERE DateTime<%d LIMIT 10000000);


Вместо %d подставляется целое число, соответствующее дате (дата в формате времени Unix).
Использую следующие настройки для базы:
Код: sql
1.
2.
PRAGMA journal_mode=WAL;
pragma cache_size=100000;


Пример данных, на которых происходит ошибка, дать не могу - там база весит уже 39Гб.
Если создаю базу с тестовыми данными вручную ошибка не происходит - удаляется ровно то количество данных, которое указано в LIMIT. Там, где работает реальная база несколько раз были аварийные отключения питания. Один раз даже восстанавливали базу через текстовое представление. Возможно, в базе есть какие-то "битые" записи, и это влияет на результаты DELETE..LIMIT? Но на запросы база отвечает корректно.
Версия движка - 3.7.17 (кстати, недоработка авторов sqlite.dll, что версию нельзя узнать из свойств самой dll в системе, не вызывая функцию по извлечению версии).
Что делать дальше? Можно изменить проверку и завершать только по условию SQLite3_Changes() = 0;
Мне просто непонятна сама причина поведения движка. Хотя, если рассуждать философски, то указание LIMIT 10000000 вроде может и не обязывать движок возвращать ровно 10000000, т.е. при каких-то условиях он может вернуть и меньше, главное - чтобы не больше.
А почему вы считаете, что удалять частями это плохо? У меня реальной альтернативы пока нет. Ошибка 'Out of memory' - это факт, подтверждённый и на тестовой базе - при удалении большого количества записей из моей базы происходит значительный рост потребления памяти (это прямо видно по "Диспетчеру задач"). Уж не знаю, чем это обусловлено, но база почему-то предпочитает не создать кэш своих данных на диске в этом случае, а именно занимает значительный объём ОЗУ.
...
Рейтинг: 0 / 0
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
    #38689966
Фотография PPA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dmitro25,

1. А если собрать последний sqlite 3.8.5
он ведет себя аналогично на тестовой копии базы?

2. У вас индекс bln,datetime а поля bln нет в where
что хранится в этом поле?

3. WAL был всегда?
...
Рейтинг: 0 / 0
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
    #38690619
Dmitro25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PPA,
1. sqlite 3.8.5 ведёт себя аналогично.
2. В поле bln хранится номер блока. Блоки перемещаются по местности и периодически передают свои геоданные, которые складываются в базу. Отдельного индекса по DateTime нет, поскольку в нём при повседневной работе с базой нет необходимости. Типовой запрос к базе всегда содержит условие и для номера блока и для даты, например:
Код: sql
1.
SELECT * FROM Data WHERE BlN=? AND DateTime BETWEEN ? and ? ORDER BY DateTime;


В запросе DELETE...LIMIT, с которым у меня странности, номер блока не указан, т.к. я хочу удалить из базы все записи (для всех блоков) старше определённого возраста.
3. WAL был не всегда. Он появился в последней версии серверной программы.
...
Рейтинг: 0 / 0
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
    #38691024
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Играйся с:
Код: sql
1.
DELETE FROM Data WHERE DateTime<%d;


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

Попробуй сделать индекс на (datetime,bln), вместо (bln,datetime). Это может помочь если у тебя нету (редки) запросов по bln, отдельно, но есть запросы по datetime отдельно.

Попробуй убирать индекс вообще на период удаления записей и потом создавать его заново. Это сэкономит память.

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

Если с WAL у тебя проблемы, попробуй отключить его. Посмотри результат. Если без разницы - смотри другие прагмы.
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / SQLite [игнор отключен] [закрыт для гостей] / По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]