Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: OR w warunku czy stworzenie unii
Forum PHP.pl > Forum > Bazy danych > MySQL
Athlan
Witam.

Ostatnio postanowiłem napisać sobie system powiadomień w serwsie. Proste powiadomienie to przypisanie rekordu użytkownikowi. Zaawansowane natomiast to takie, które jes
 rozsyłane do wszystkich przyjaciół uzytkownika. No wiadomo, nie będę rozsyłał d
 wszystkich userów po rekordzie, tylko rozpiszę tabelę trochę inaczej. Oto jej s
ruktura:

(klucz notice_owner napisany testowo)

  1. CREATE TABLE `notice` (
  2. `notice_id` int(11) NOT NULL AUTO_INCREMENT,
  3. `notice_type` smallint(2) NOT NULL DEFAULT '0',
  4. `notice_owner` int(11) NOT NULL DEFAULT '0',
  5. `notice_user` int(11) NOT NULL DEFAULT '0',
  6. `notice_item` int(11) NOT NULL DEFAULT '0',
  7. `notice_self` smallint(1) NOT NULL DEFAULT '0',
  8. PRIMARY KEY (`notice_id`),
  9. KEY `notice_normal` (`notice_owner`),
  10. KEY `notice_relation` (`notice_user`,`notice_self`),
  11. KEY `notice_owner` (`notice_owner`,`notice_user`,`notice_self`)
  12. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;


Opis pól (ważniejszych):
notice_owner - "posiadacz" powiadomienia
notice_user - id user na temat którego jest powiadomienie

Wykorzystanie.
  • Gdy chcemy zaznaczyć powiadomienia usera w trybie prostym, szukamy rekordów po notice_owner
  • Gdy chcemy szukać powiadomień na temat przyjaciół, musimy wybrać najpierw listę przyjaciół (subzapytanie) i szukać po notice_user i notice_self zaznaczonym na 1.
2 zapytania, które lepsze:

PIERWSZE (unia):

  1. EXPLAIN SELECT notice_type, user_name, user_id
  2. FROM notice LEFT JOIN users ON ( user_id = notice_user )
  3. WHERE notice_owner =31385
  4. UNION SELECT notice_type, user_name, user_id
  5. FROM notice LEFT JOIN users ON ( user_id = notice_user )
  6. WHERE notice_self =1 AND notice_user
  7. IN (
  8.  
  9. SELECT friend_id
  10. FROM friends WHERE friend_owner =31385
  11. )


(wykorzystane wszystkie klucze, oprócz notice_owner bo tego zapytania się on nie tyczy. Wyskakuje EXTRA w unii: Impossible WHERE noticed after reading const table...)

DRUGIE (z wykorzystaniem OR):
  1. SELECT notice_type, user_name, user_id FROM notice LEFT JOIN users ON (user_id = notice_user) WHERE notice_owner = 31385 OR (notice_self = 1 AND notice_user IN(SELECT friend_id FROM friends WHERE friend_owner = 31385))

(tutaj nie korzysta się z klucza notice_owner)

Pytania:
a ) które zapytanie jest bardziej optymalne (proszę wziąć pod uwagę brak wykorzystania klcza w OR, jeżeli da się go jakoś zbudować, to jak)
b ) niepokoi mnie komunikat w EXTRA przy pierwszym zapytaniu dla unii: Impossible WHERE noticed after reading const table...

Dziekuję za wypowiedzi.
Sedziwoj
Właśnie czytam i jakoś nie do końca rozumiem. Powinieneś najpierw napisać co ma być robione (tak dla laików) a potem sposób w jaki chcesz rozwiązać to. Bo nie jestem pewien czy dobrze zrozumiałem.
A nie możesz tego rozbić? Czyli stworzyć coś co trzyma relacje użytkownik - przyjaciele, czy ogólniej użytkownik - powiadomienie.
Takie user_id,notice_id,type_id...
Wtedy indeks na user_id i dwukolumnowy na user_id i type_id, aby móc wybrać tylko danego typu powiadomienia.
Jeśli ma być ważna data to też dodać i zineksować. To taka tabela służąca do wyszukania elementów, gdy masz tylko te co potrzebujesz dołączasz dopiero dane (nieważne przy wyszukiwaniu a najczęściej sporo ważące).
Athlan
Sęk w tym, że przy warunku OR:

Dla przypadków połączonych tą klauzulą:
a ) po notice_owner = ID_USERA_POWIADAMIANEGO
b ) po notice_owner = 0 i notice_self = 1 i notice_user IN( PRZYJACIELE_USERA_POWIADAMIANEGO )

, nie wykorzystywany jest żaden z wyżej wymienionych (które podałem w załączonych listingach) kluczy (badane EXPLAIN)
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.