Как удалить фиксированное количество строк с сортировкой в PostgreSQL?



Я пытаюсь перенести некоторые старые запросы MySQL на PostgreSQL, но у меня возникли проблемы с этим:



DELETE FROM logtable ORDER BY timestamp LIMIT 10;


PostgreSQL не позволяет упорядочивать или ограничивать синтаксис удаления, а таблица не имеет первичного ключа, поэтому я не могу использовать подзапрос. Кроме того, я хочу сохранить поведение, когда запрос удаляет ровно заданное число или записи -- например, если таблица содержит 30 строк, но все они имеют одинаковую метку времени, я все равно хочу удалить 10, хотя это не имеет значения, что 10.



Итак; как удалить фиксированное количество строк с сортировкой в PostgreSQL?



Edit: нет первичного ключа означает, что нет log_id столбец или аналогичный. Ах, радости унаследованных систем!

616   6  

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));

этот и некоторые другие трюки можно найти здесь

delete from logtable where log_id in (
    select log_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

    Ничего не найдено.