Mam kilka wierszy, które muszę wstawić do tabeli, ale te wstawki są zawsze wykonywane partiami. Chcę więc sprawdzić, czy w tabeli istnieje pojedynczy wiersz z partii, ponieważ wtedy wiem, że wszystkie zostały wstawione.
Więc nie jest to klucz podstawowy, ale nie powinien mieć większego znaczenia. Chciałbym sprawdzić tylko jeden wiersz, więc count(*)
prawdopodobnie nie jest dobry, więc exists
myślę, że jest to coś takiego .
Ale ponieważ jestem całkiem nowy w PostgreSQL, wolałbym zapytać ludzi, którzy wiedzą.
Moja partia zawiera wiersze o następującej strukturze:
userid | rightid | remaining_count
Więc jeśli tabela zawiera jakiekolwiek wiersze z podaniem userid
, oznacza to, że wszystkie tam są.
sql
postgresql
Valentin Kuzub
źródło
źródło
Odpowiedzi:
Użyj słowa kluczowego EXISTS dla powrotu PRAWDA / FAŁSZ:
źródło
select exists(select 1 from contact where id=12) AS "exists"
exists
lublimit 1
mam duży spadek wydajności, ponieważ Postgres używa Seq Scan zamiast Index Scan. Ianalyze
nie pomaga.A może po prostu:
gdzie
123
jest identyfikator użytkownika partii, którą zamierzasz wstawić.Powyższe zapytanie zwróci pusty zestaw lub pojedynczy wiersz, w zależności od tego, czy istnieją rekordy o podanym identyfikatorze użytkownika.
Jeśli okaże się to zbyt wolne, możesz spróbować utworzyć indeks
tbl.userid
.Aby pozostało to prawdą, nawet jeśli program zostanie przerwany w połowie partii, radziłbym upewnić się, że odpowiednio zarządzasz transakcjami bazy danych (tj. Cała partia jest wstawiana w ramach jednej transakcji).
źródło
COUNT
Działa na zagnieżdżoneSELECT
, że zawiera co najwyżej 1 rząd (ponieważLIMIT
jest podkwerendzie).BTW: jeśli chcesz, aby cała partia zakończyła się niepowodzeniem w przypadku duplikatu, to (biorąc pod uwagę ograniczenie klucza podstawowego)
zrobi dokładnie to, czego chcesz: albo się powiedzie, albo zawiedzie.
źródło
Uważam, że jest to zapytanie, którego używa postgres do sprawdzania kluczy obcych.
W twoim przypadku możesz to zrobić za jednym razem:
źródło
jak wskazał @MikeM.
z indeksem przy kontakcie może zwykle zmniejszyć koszt czasu do 1 ms.
źródło
Jeśli zestaw wyników zawiera wiersz, nie musisz go wstawiać. W przeciwnym razie wprowadź swoje rekordy.
źródło
Jeśli myślisz o performace, być może możesz użyć „PERFORM” w funkcji takiej jak ta:
źródło
Chciałbym zaproponować inną myśl, aby konkretnie odnieść się do twojego zdania: „Chcę więc sprawdzić, czy w tabeli istnieje pojedynczy wiersz z partii, ponieważ wtedy wiem, że wszystkie zostały wstawione ”.
Robisz rzeczy wydajnie, wstawiając „partie”, ale potem sprawdzanie istnienia sprawdza tylko jeden rekord na raz? Wydaje mi się to sprzeczne z intuicją. Więc kiedy mówisz „ wstawianie zawsze wykonuje się partiami ”, rozumiem, że masz na myśli wstawianie wielu rekordów za pomocą jednej instrukcji wstawiania . Musisz zdać sobie sprawę, że Postgres jest zgodny z ACID. Jeśli wstawiasz wiele rekordów (zestaw danych) za pomocą jednej instrukcji wstawiania , nie ma potrzeby sprawdzania, czy niektóre zostały wstawione, czy nie. Instrukcja przechodzi lub zakończy się niepowodzeniem. Wszystkie rekordy zostaną wstawione lub żadne.
Z drugiej strony, jeśli Twój kod C # po prostu wykonuje „set” oddzielne instrukcje wstawiania, na przykład w pętli, i myślisz, że jest to „partia”… to nie powinieneś opisywać tego jako „ wkładki są zawsze wykonywane partiami ”. Fakt, że spodziewasz się, że część tego, co nazywasz „pakietem”, może w rzeczywistości nie zostać włożona, a zatem odczuwasz potrzebę sprawdzenia, zdecydowanie sugeruje, że tak jest, w takim przypadku masz bardziej podstawowy problem. Musisz zmienić swój paradygmat, aby faktycznie wstawić wiele rekordów za pomocą jednej wstawki i zrezygnować z sprawdzania, czy pojedyncze rekordy to zrobiły.
Rozważmy ten przykład:
W rzeczywistości jest to paradygmat dla każdej bazy danych zgodnej z ACID .. nie tylko Postgresql. Innymi słowy, lepiej będzie, jeśli naprawisz koncepcję „partii” i unikniesz konieczności sprawdzania każdego wiersza w pierwszej kolejności.
źródło