Próbuję przenieść niektóre stare zapytania MySQL do PostgreSQL, ale mam problem z tym:
DELETE FROM logtable ORDER BY timestamp LIMIT 10;
PostgreSQL nie pozwala na porządkowanie ani ograniczenia w swojej składni usuwania, a tabela nie ma klucza podstawowego, więc nie mogę użyć podzapytania. Dodatkowo chcę zachować zachowanie, w którym zapytanie usuwa dokładnie podaną liczbę lub rekordy - na przykład, jeśli tabela zawiera 30 wierszy, ale wszystkie mają ten sam znacznik czasu, nadal chcę usunąć 10, chociaż nie ma to znaczenia który 10.
Więc; jak usunąć określoną liczbę wierszy z sortowaniem w PostgreSQL?
Edycja: brak klucza podstawowego oznacza brak log_id
kolumny lub podobnej. Ach, radości ze starszych systemów!
sql
postgresql
Co to
źródło
źródło
alter table foo add column id serial primary key
.Odpowiedzi:
Możesz spróbować użyć
ctid
:ctid
Jest:Istnieje również,
oid
ale istnieje tylko wtedy, gdy specjalnie o to poprosisz podczas tworzenia tabeli.źródło
VACUUM FULL
odkurzanie lub wywoływanie problemów, jeśli zmieniająctid
wartości w tabeli w trakcie wykonywania zapytania?ctid
dokumentacja jestctid
wystarczająco stabilna, aby to DELETE działało poprawnie, ale nie jest wystarczająco stabilna, aby na przykład umieścić w innej tabeli jako getto-FK. Prawdopodobnie nie AKTUALIZUJESZ,logtable
więc nie musisz się martwić o zmianęctid
s iVACUUM FULL
blokujesz tabelę ( postgresql.org/docs/current/static/routine-vacuuming.html ), więc nie musisz się martwić inny sposób, któryctid
może się zmienić. PostgreSQL-Fu @ araqnid jest dość mocny i dokumentacja zgadza się z nim, aby uruchomić.Dokumenty Postgres zalecają używanie tablicy zamiast IN i podzapytania. To powinno działać znacznie szybciej
To i kilka innych sztuczek można znaleźć tutaj
źródło
any (array( ... ));
jest szybszy niżin ( ... )
to, brzmi jak błąd w optymalizatorze zapytań - powinien być w stanie wykryć tę transformację i zrobić to samo z samymi danymi.IN
naUPDATE
(co może być różnicą).źródło
Zakładając, że chcesz usunąć JAKIEKOLWIEK 10 rekordów (bez zamawiania), możesz to zrobić:
W moim przypadku usunięcia 10M rekordów okazało się to szybsze.
źródło
Mógłbyś napisać procedurę, która zapętla usuwanie dla poszczególnych linii, procedura może przyjmować parametr określający liczbę elementów, które chcesz usunąć. Ale to trochę przesada w porównaniu z MySQL.
źródło
Jeśli nie masz klucza podstawowego, możesz użyć składni tablicy Where IN z kluczem złożonym.
To zadziałało dla mnie.
źródło