Как удалить фиксированное количество строк с сортировкой в PostgreSQL?
Я пытаюсь перенести некоторые старые запросы MySQL на PostgreSQL, но у меня возникли проблемы с этим:
DELETE FROM logtable ORDER BY timestamp LIMIT 10;
PostgreSQL не позволяет упорядочивать или ограничивать синтаксис удаления, а таблица не имеет первичного ключа, поэтому я не могу использовать подзапрос. Кроме того, я хочу сохранить поведение, когда запрос удаляет ровно заданное число или записи -- например, если таблица содержит 30 строк, но все они имеют одинаковую метку времени, я все равно хочу удалить 10, хотя это не имеет значения, что 10.
Итак; как удалить фиксированное количество строк с сортировкой в PostgreSQL?
Edit: нет первичного ключа означает, что нет log_id столбец или аналогичный. Ах, радости унаследованных систем!
6 ответов:
вы можете попробовать использовать
ctid:DELETE FROM logtable WHERE ctid IN ( SELECT ctid FROM logtable ORDER BY timestamp LIMIT 10 )The
ctid- это:физическое расположение строк в таблице. Обратите внимание, что хотя
ctidможно использовать для быстрого поиска версии строки, строкиctidизменится, если он будет обновлен или перемещенVACUUM FULL. Поэтомуctidбесполезен в качестве долгосрочного идентификатора строки.там же
oidно это существует, только если вы конкретно попросите его при создании таблицы.
Постгреса врачи рекомендуют использовать массив, а не в подзапросе. Это должно работать намного быстрее
DELETE FROM logtable WHERE id = any (array(SELECT id FROM logtable ORDER BY timestamp LIMIT 10));этот и некоторые другие трюки можно найти здесь
предполагая, что вы хотите удалить любые 10 записей (без заказа) , вы можете сделать это:
DELETE FROM logtable as t1 WHERE t1.ctid < (select t2.ctid from logtable as t2 where (Select count(*) from logtable t3 where t3.ctid < t2.ctid ) = 10 LIMIT 1);для моего случая использования, удаление записей 10M, это оказалось быстрее.
вы можете написать процедуру, которая зацикливается на удалении для отдельных строк, процедура может принять параметр, чтобы указать количество элементов, которые вы хотите удалить. Но это немного перебор по сравнению с MySQL.
Если у вас нет первичного ключа, вы можете использовать массив, где в синтаксисе с составным ключом.
delete from table1 where (schema,id,lac,cid) in (select schema,id,lac,cid from table1 where lac = 0 limit 1000);это сработало для меня.
Comments