![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 162 Pomógł: 13 Dołączył: 16.06.2007 Ostrzeżenie: (0%) ![]() ![]() |
Witam,
otóż tworząc pewien projekt zapewniam sobie spójność danych kilkoma warunkami w kodzie (a w zasadzie odpowiednim zapytaniem). Ale w procesie optymalizacji całej aplikacji zacząłem większość rzeczy wrzucać do bazy (triggery, indeksy na wielu polach itp). Zastanawiałem się też nad pewną kwestią - nazwijmy to znajomość użytkowników. Przykład: Użytkownik A (user_a w DB) jest znajomym z Użytkownikiem B (user_b). Tym samym B jest znajomym z A. Do opisania tej zależności potrzebny jest jeden rekord z id znajomości, id user_a, id_user_b i np created_at. Jak założyć taki indeks aby unikalna była para (user_a, user_b) oraz (user_b, user_a). Zakładając że user_a ma id 1 a user_b - 100 to unikalne muszą być 2 pary (1,100) oraz (100,1). Mam nadzieję że jasno opisałem problem. PS. Sprawdzenie w kodzie czy już istnieje znajomość jest banalne - "SELECT COUNT(*) FROM relations WHERE (user_a = 1 AND user_b = 100) OR (user_b=1 AND user_a=100)" ale chciałbym dodatkowo zabezpieczyć bazę. |
|
|
![]() |
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 1 890 Pomógł: 339 Dołączył: 14.12.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Możesz założyć zwykły index UNIQUE, a w kodzie aplikacji zapewnić, że niższe ID użytkownika będzie zapisywane w kolumnie id_user_a, a wyższe w id_user_b. Więc nie będziesz zapisywał (100, 1), tylko zawsze (1, 100).
Może nie jest to do końca rozwiązanie o jakie pytałeś, ale... działa (IMG:style_emoticons/default/Lkingsmiley.png) |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 162 Pomógł: 13 Dołączył: 16.06.2007 Ostrzeżenie: (0%) ![]() ![]() |
Tak nie do końca bo np. przyjmuję że user_a zaprosił usera_b do znajomości (takie dane historyczne). Pewnie da się dodać do tego dodatkową kolumnę z osobą rozpoczynającą znajomość ale to już trochę nieeleganckie
|
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 279 Pomógł: 56 Dołączył: 3.06.2010 Skąd: Tarnowskie Góry Ostrzeżenie: (0%) ![]() ![]() |
Z punktu widzenia bazy danych rekordy (1,100) i (100,1) to zupełenie inne wpisy, więc nie ma potrzeby zabezpieczać się na takie wypadki. Zaimplementowane w bazie mechanizmy służą zabezpieczeniu integralności danych, a w tym wypadku nie ma takiej potrzeby.
Skorzystaj z tego co zaproponował @sowiq. Do tego dodaj pole bitowe: 0 - zaprosił użytkownik A, 1 - użytkownik B i po kłopocie. Nie widzę w tym nic nieeleganckiego, widzę raczej proste rozwiązanie problemu. |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 162 Pomógł: 13 Dołączył: 16.06.2007 Ostrzeżenie: (0%) ![]() ![]() |
W sumie racja, może za bardzo chce na siłę "upiększać" rozwiązanie.
|
|
|
![]()
Post
#6
|
|
Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Stosując rozwiązanie ~sowiq zwróć uwagę w jaki sposób wyciągasz znajomych danego użytkownika (sam podałeś ich zliczanie). Dając w warunku OR utrudniasz MySQL "życie" - nie będzie w stanie prawidłowo skorzystać z indeksu. Zobacz jak będzie wyglądał EXPLAIN takiego zapytania. Rozwiązaniem tego problemu będzie rozbicie zapytania na 2 osobne i połączenie ich za pomocą UNION. Czyli zamiast:
zrób:
|
|
|
![]() ![]() |
![]() |
Aktualny czas: 24.08.2025 - 13:40 |