|
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
|
|||
---|---|---|---|
#18+
Здравствуйте. На базе в несколько сотен миллионов записей выполняется удаление устаревших записей. При этом просто удаление Код: sql 1.
не работает (программа, выполняющая запрос, в процессе запроса начинает занимать всю доступную память, и запрос прерывается с ошибкой "Out of memory"). В результате было решено удалять частями: Код: sql 1.
данный запрос повторяется до тех пор, пока возвращённое функцией SQLite3_Changes() количество затронутых запросом записей не станет меньше 10000000. Однако, наблюдается странная ситуация: первый же запрос на удаление возвращает не 10000000, а 9999998 затронутых запросом записей, и, в результате, дальнейшие запросы не производятся. Количество записей в базе, которые удовлетворяют условию запроса, значительно больше 10000000. Мало того, если я вручную снова запускаю процедуру удаления, снова возвращается то же число 9999998 затронутых записей. Подскажите, по какой причине такое может получаться? ... |
|||
:
Нравится:
Не нравится:
|
|||
04.07.2014, 11:16 |
|
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
|
|||
---|---|---|---|
#18+
Dmitro25Здравствуйте. На базе в несколько сотен миллионов записей выполняется удаление устаревших записей. При этом просто удаление Код: sql 1.
не работает (программа, выполняющая запрос, в процессе запроса начинает занимать всю доступную память, и запрос прерывается с ошибкой "Out of memory").А ты уверен что DateTime хранит данные в том же самом формате в котором ты константу отдаешь? Показывай полный исходник и пример данных. Заодно уточни версию движка. Dmitro25В результате было решено удалять частями: Код: sql 1.
В морг. Кривое решение, могущее принести в миллионы раз больше проблем. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.07.2014, 21:07 |
|
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
|
|||
---|---|---|---|
#18+
White Owl Вот формат таблицы для хранения данных Код: sql 1. 2. 3.
Вот точный sql-запрос на удаление Код: sql 1.
Вместо %d подставляется целое число, соответствующее дате (дата в формате времени Unix). Использую следующие настройки для базы: Код: sql 1. 2.
Пример данных, на которых происходит ошибка, дать не могу - там база весит уже 39Гб. Если создаю базу с тестовыми данными вручную ошибка не происходит - удаляется ровно то количество данных, которое указано в LIMIT. Там, где работает реальная база несколько раз были аварийные отключения питания. Один раз даже восстанавливали базу через текстовое представление. Возможно, в базе есть какие-то "битые" записи, и это влияет на результаты DELETE..LIMIT? Но на запросы база отвечает корректно. Версия движка - 3.7.17 (кстати, недоработка авторов sqlite.dll, что версию нельзя узнать из свойств самой dll в системе, не вызывая функцию по извлечению версии). Что делать дальше? Можно изменить проверку и завершать только по условию SQLite3_Changes() = 0; Мне просто непонятна сама причина поведения движка. Хотя, если рассуждать философски, то указание LIMIT 10000000 вроде может и не обязывать движок возвращать ровно 10000000, т.е. при каких-то условиях он может вернуть и меньше, главное - чтобы не больше. А почему вы считаете, что удалять частями это плохо? У меня реальной альтернативы пока нет. Ошибка 'Out of memory' - это факт, подтверждённый и на тестовой базе - при удалении большого количества записей из моей базы происходит значительный рост потребления памяти (это прямо видно по "Диспетчеру задач"). Уж не знаю, чем это обусловлено, но база почему-то предпочитает не создать кэш своих данных на диске в этом случае, а именно занимает значительный объём ОЗУ. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.07.2014, 15:40 |
|
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
|
|||
---|---|---|---|
#18+
Dmitro25, 1. А если собрать последний sqlite 3.8.5 он ведет себя аналогично на тестовой копии базы? 2. У вас индекс bln,datetime а поля bln нет в where что хранится в этом поле? 3. WAL был всегда? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2014, 06:55 |
|
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
|
|||
---|---|---|---|
#18+
PPA, 1. sqlite 3.8.5 ведёт себя аналогично. 2. В поле bln хранится номер блока. Блоки перемещаются по местности и периодически передают свои геоданные, которые складываются в базу. Отдельного индекса по DateTime нет, поскольку в нём при повседневной работе с базой нет необходимости. Типовой запрос к базе всегда содержит условие и для номера блока и для даты, например: Код: sql 1.
В запросе DELETE...LIMIT, с которым у меня странности, номер блока не указан, т.к. я хочу удалить из базы все записи (для всех блоков) старше определённого возраста. 3. WAL был не всегда. Он появился в последней версии серверной программы. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2014, 15:29 |
|
По какой причине (DELETE ... LIMIT) может удалять меньше записей, чем прописано в LIMIT
|
|||
---|---|---|---|
#18+
Играйся с: Код: sql 1.
Если этот запрос захапывает всю доступную память, отмотай константу дальше в прошлое. Вплоть до удаления отдельными кусочками по одному дню, получасу или даже секунде. В конце концов ты найдешь наиболее оптимальное значение. Попробуй сделать индекс на (datetime,bln), вместо (bln,datetime). Это может помочь если у тебя нету (редки) запросов по bln, отдельно, но есть запросы по datetime отдельно. Попробуй убирать индекс вообще на период удаления записей и потом создавать его заново. Это сэкономит память. Есть ли триггеры и внешние ключи ссылающиеся на проблемную таблицу? Если есть - удаляй эти связи пока не заработает. Если с WAL у тебя проблемы, попробуй отключить его. Посмотри результат. Если без разницы - смотри другие прагмы. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.07.2014, 18:58 |
|
|
start [/forum/topic.php?desktop=1&fid=54&tid=2008774]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
44ms |
get topic data: |
14ms |
get forum data: |
3ms |
get page messages: |
48ms |
get tp. blocked users: |
2ms |
others: | 13ms |
total: | 155ms |
0 / 0 |