TwojePC.pl © 2001 - 2024
|
|
A R C H I W A L N A W I A D O M O Ś Ć |
|
|
|
Znowu filozoficznie: Jak najeleganciej inicjalizować id obiektów? , ptoki 11/06/13 10:43 Jest sobie aplikacja. W niej tworzone są obiekty.
No i dobrze było by im ponadawać ID.
Metody jakie znam:
1. Wybrać z tabelki max(id) i nowy obiekt załadować z max(id)+1. (tu problem z warunkami wyścigowymi i synchronizowaniem wątków)
2. Załadować do bazy bez id (niech baza sama utworzy) z nazwą "techniczną" - cos w rodzaju "nazwa_pusta_ble_ple", potem zrobić select takiej nazwy, dostać id i już taki id zupdateować. (tu problem z nadmiarowością operacji - ale mniejszy niż w przypadku pierwszym).
Jest jakaś inna metoda?
Jakieś select last_autoincremented_by_my_connection?
Narazie grzebie w sqlite ale ciekawi mnie czy w innych motorach bazodanowych są jakieś eleganckie rozwiązania?- zalezy od bazy danych , endern 11/06/13 10:58
ale pod sql server tez powinno coś być.
Pod Oracle definiujesz sekwencję:
http://www.orafaq.com/...7712/155200/0/#msg_155200- wielowątkowości , endern 11/06/13 10:59
nie testowałem, ale silnik bazy danych powinien pilnować tego dobrze.
jakby nie to jeszcze można bawić się trybami dostępu do tabeli.- Silnik powinien pilnować. Ale właśnie widac po powyższym przykłądzie jak dziwne implementa , ptoki 11/06/13 11:20
cje są w bazach.
Narazie pojade z moim drugim wariantem bo soft jest prosty ale chciałbym się dowiedzieć jak sie to ogólnie robi.
W jednym z duzych softów jakie widziałem był centralny mechanizm robienia ID i tam bbył on osadzony na bazie więc dosyć dobrze pilnował unikalności i dbał aby nie było dziur w numeracji.- ej... , endern 11/06/13 11:33
no ta implementacja jest prosta i czytelna. Bardzo ładnie jest to rozwiązane właśnie w Oracle.
Definujesz tylko sekwencję:
create sequence employee_Id_sequence
start with 1
increment by 1;
a potem tylko odwołujesz się do niej(employee_Id_sequence.nextval) przy insertach:
select employee_Id_sequence.nextval
into :new.employee_ID
from dual;
Choć z takimi funkcjonalnościami może być gorzej już przy prostszych silnikach bazodanowych.
Jeśli nie ma tego mechanizmu w sqllite, to ja bym napisal procedure, funkcję odpowiedzialną za jego generowanie. Z zmienną globalną?.
W moim odczuciu twój pkt 2 nie rozwiązuje problemu wielowątkowości.
Nie wymądrzam się gdyż nie jestem rasowym bazowym developerem, może ktoś zaproponuje bardziej pro podejscie ;)- Na tym etapie tak, ale widziales jaki cyrk sie dzieje jak robisz eksport i import? , ptoki 11/06/13 12:55
No i jak wtedy ten id integruje sie z czymś innym (nie koniecznie w tej bazie) to sie robią cyrki i trzeba sobie samemu robić dodatkowe ID.
To oraklowe rozwiazanie jest ok ale też wprowadza pewne problemy w innym miejscu. Samo generowanie unikalnego ID jest działające.
- Oracle zapewnia unikatowość podawanych z sekwencji identyfikatorów , bwana 11/06/13 14:57
Można nawet w gridzie baz Oracle uzyskać sekwencje unikatowe w obrębie grida.
Należy pamiętać o kilku rzeczach - żeby nie zrobić sobie kuku:
1. Jeśli pobieramy nową wartość sekwencji w transakcji którą odrzucamy (rollback) to ta wartość przepada - następna transakcja dostanie już kolejną wartość. Nie wolno zakładać, że identyfikatory kolejno zapisane w bazie będą zbiorem 1, 2, 3... (bez dziur)
2. Sekwencja w Oracle nie musi podawać wartości monotonicznie (rosnąco). Może się okazać, że zapisane w czasie wartości sekwencji są w "dziwnej" kolejności (jedna sesja zbuforowała sobie 10 kolejnych wartości sekwencji, inna kolejne 10 i pozapisywały się naprzemian). Aby zapewnić monotoniczność sekwencji, należy stworzyć ją z klauzulą WITH GUARANTEED ORDER."you don't need your smile when I cut
your throat" - Dzieki za zajawke. Mi raczej chodzilo o inny aspekt ale , ptoki 11/06/13 22:05
i te informacje sie przydadzą.
- Tak jak napisał endern... , pi_3-14 11/06/13 12:13
w sqlite czy mysql masz specjalny typ pola "autoincrement" i on pilnuje żeby były wartości unikalne, przy insercie nie podajesz po prostu tego pola, defaultowo tworzą się nowe wartości
w oracle cz postgresql do tego służą sekwenecje. mozesz mieć jedną sekwencję na całą bazę (co powoduje że niezależnie od tabeli każdy rekord ma swoje unikatowe id) możesz tworzyć sekwencje do każdej tabeli - jak ci wygodnie. i tutaj też silnik zadba żeby nie było duplikatów
Problem z id może być przy rozproszonych bazach i shardingu - ale na to też są sposoby, do znalezienie w google.- No właśnie, autoincrement jest ok. Tylko jak dostać właśnie włożone ID? , ptoki 11/06/13 12:57
w mysql/sqlite?
Da sie eleganciej niż w metodzie 2?- w MySQL - LAST_INSERT_ID() , pi_3-14 11/06/13 13:17
zależy jak używasz itp. np. w PHP
http://php.net/.../en/function.mysql-insert-id.php
to jest właśnie "last_autoincremented_by_my_connection"- Dzieki. Już jasne. , ptoki 11/06/13 13:44
W php działa. Obacze jak sie zachowuje w javie...
- jeżeli na podstawie bazy , Wedrowiec 11/06/13 12:36
to jak wyżej masz autoincrement a w mysql po insercie wywołujesz mysql_insert_id i zwraca Ci id tego rekordu"Widziałem podręczniki
Gdzie jest czarno na białym
Że jesteście po**bani" - ten mysql_insert_id dba o to aby mi w jednym wątku podać id włozone w tym wątku , ptoki 11/06/13 12:58
a nie id włozonego z innego wątku/innej instancji aplikacji?
Bo to jest to o co pytałem pi_3_14...- myślałem że tak, , Wedrowiec 11/06/13 13:26
poczytałem w manualu... i już nie wiem :) informacje w komentarzach są sprzeczne :D"Widziałem podręczniki
Gdzie jest czarno na białym
Że jesteście po**bani" - Ciesze sie ze odnieslismy obopólną korzyść przy czym ja do przodu , ptoki 11/06/13 13:45
a ty na pewno nie do tyłu ;)
Juz mi sie do bazy zapisuje i czyta. Na testy czy sie wątki nie mieszają przyjdzie czas później :)
- bazy mają wiele machanizmów , szarp 11/06/13 12:46
- sekwencja
- kolumna identity
- kolumna serial
- rowid
...KS - Tu znalazlem najsensowniejszą odpowiedź. Choć , ptoki 11/06/13 13:07
nie do końca jest wyjaśnione że takie podejście zawsze gwarantuje unikalność i precyzję zwróconego ID (tak w wątku jak i dla wielu połączeń)
http://stackoverflow.com/...using-sqlite-from-java - Każdy motor relacyjny powinien mieć coś takiego, tylko że to może nie być optymalne roz- , bwana 11/06/13 14:53
wiązanie. Pytanie, czy sięganie do bazy danych po taki ID ma sens w warunkach:
- gdy tworzony obiekt nie ma być obiektem bazodanowym albo jego ID w bazie nie ma znaczenia dla jego identyfikacji w kodzie programu
- gdy tworzony obiekt działa w procesie poza bazą (np. w Javie, PHP czy czymś takim)
- gdy takich obiektów będziesz tworzyć pierdygigalion na sekundę
- gdy architektura aplikacji jest taka, że baza danych i serwer aplikacji działają na osobnych maszynach
Narzut na komunikację warstwy logiki z bazą danych może być duży. Do tego jeśli unikatowość ID ma być zapewniona tylko w obrębie danej sesji a nie w aplikacji, to w ogóle jest to wyjście z armatą na komara.
W Javie masz np. klasę UUID - http://www.javapractices.com/...picAction.do?Id=56
W PHP też masz do tego narzędzie - http://php.net/manual/pl/function.uniqid.php
które być może wystarczy Ci."you don't need your smile when I cut
your throat" - Dzieki za zajawki. O wydajnosci bazy dla malych operacji , ptoki 11/06/13 22:09
Dobrze wiem. Nie raz na tym sie przejechalem.
W tym co teraz dlubie wlasnie chodzi o to aby przeciwczyc unikalnosc i rozproszenie.
Normalnie bym pchal dane w tabelke i "uchwyt" dla aplikacju bylby zwyklym id z bazy (jakis rowid czy inny autoincrementowany id).
Ale tu akurat chodzi aby w momencie tworzenia obiektu miał on już unikalny uchwyt. Jeszcze zanim zapisze sie w bazie.- w takim przypadku postarałbym się (w zależności od architektury) , bwana 11/06/13 22:27
o taki model:
na maszynie/w procesie/w warstwie (lub jak najbliżej warstwy) gdzie dzieje się tworzenie nowych obiektów zapewniłbym mechanizm generowania unikatowego ID (unikatowego w obrębie całej aplikacji a nie sesji) i do bazy wysyłał obiekt już z posiadanym tak uzyskanym identyfikatorem. Dzięki temu jedno stworzenie obiektu będzie komunikowało się z bazą danych jednokrotnie (zapis kompletnego obiektu) a nie dwukrotnie (weź z bazy ID do klienta/warstwy/procesu, zapisz obiekt).
Rzecz jasna - jeśli masz pewność że w dłuższym czasie utrzymania aplikacji:
- baza i warstwa/proces generujące obiekty są "blisko" w sieci (ta sama maszyna)
- lub liczba tworzonych obiektów w czasie jest niewielka
to spokojnie możesz faktycznie posłużyć się sekwencją uzyskaną z bazy danych. Narzut na pobieranie ID z bazy do kliena/warstwy tworzącej obiekt może w takiej sytuacji okazać się pomijalny dla wydajności.
W ostateczności, o ile nie potrzebujesz tego ID w procesie który tworzy obiekt, możesz zrobić tak:
- stworzyć w kliencie (ogólnie - tej warstwie która tworzy obiekty) obiekt bez ID
- wysłać go do bazy danych
- w bazie zrobić trigger, który dla wstawianych rekordów w odpowiedniej kolumnie wstawia ID z sekwencji
W zależności od "cyklu życia" takiego obiektu na kliencie może to być wystarczające. Ale przy takim modelu musisz pamiętać - żeby posłużyć się w kliencie ID obiektu, będziesz musiał obiekt ponownie wczytać z bazy wraz z tym ID.
Jak widać o byle pierdole można książki pisać:)"you don't need your smile when I cut
your throat" - Ten problem obok braku standardu faktury elektronicznej jest tym co mnie zawsze dziwiło , ptoki 12/06/13 07:34
ze nie jest sensownie zrobione, raz a dobrze.
Dzieki za informacje.
|
|
|
|
|
All rights reserved ® Copyright and Design 2001-2024, TwojePC.PL |
|
|
|
|