Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak zaimplementować system tagowania podobny do SO w php/mysql?

Zanim przejdziemy do przedwczesnej optymalizacji trybie, przydatne może być zajrzenie do następującego szablonu zapytania. Jeśli nic więcej, może to być wykorzystane jako punkt odniesienia, względem którego można mierzyć skuteczność możliwych optymalizacji.

SELECT T.Tagid, TagInfo.TagName,  COUNT(*)
FROM Items I
JOIN Tags TagInfo ON TagInfo.TagId = T.TagId
JOIN ItemTagMap T  ON I.ItemId = T.ItemId 
--JOIN ItemTagMap T1 ON I.ItemId = T1.ItemId
WHERE I.ItemId IN
  (
      SELECT ItemId 
      FROM Items
      WHERE   -- Some typical initial search criteria
         Title LIKE 'Bug Report%'   -- Or some fulltext filter instead...
         AND  ItemDate > '02/22/2008'
         AND  Status = 'C'
  )
--AND T1.TagId = 'MySql'
GROUP BY T.TagId, TagInfo.TagName
ORDER BY COUNT(*) DESC

Podzapytanie to „zapytanie sterujące”, czyli takie, które odpowiada początkowym kryteriom użytkownika końcowego. (patrz poniżej, aby uzyskać szczegółowe informacje na temat tego, jak to zapytanie, wymagane wielokrotnie, może zmieścić się w ogólnie zoptymalizowanym przepływie) Skomentowane jest JOIN na T1 (i prawdopodobnie T2, T3, gdy wybrano kilka tagów) oraz, z klauzulą ​​WHERE, powiązane kryteria. Są one potrzebne, gdy użytkownik wybierze konkretny tag, czy to w ramach wstępnego wyszukiwania, czy poprzez zawężenie. (Bardziej wydajne może być umieszczenie tych łączeń i klauzul gdzie w podzapytaniu; więcej o nich poniżej)

Dyskusja... „Zapytanie kierowcy” lub jego odmiana jest potrzebne do dwóch różnych celów:

  • 1 aby dostarczyć kompletne lista ItemId, która jest potrzebna do wyliczenia wszystkich powiązanych tagów.

  • 2 w celu podania pierwszych N wartości ItemId (N oznacza rozmiar wyświetlanej strony), w celu wyszukania szczegółowych informacji o pozycji w tabeli Item.

Zwróć uwagę, że pełna lista nie musi być sortowana (lub może skorzystać na sortowaniu w innej kolejności), przy czym druga lista musi być posortowana na podstawie wyboru użytkownika (powiedzmy według daty, malejąco lub według tytułu, alfabetycznie rosnąco ). Należy również zauważyć, że jeśli wymagana jest jakakolwiek kolejność sortowania, koszt zapytania będzie sugerował, że zajmiemy się pełną listą (niezależnie od dziwnej optymalizacji przez sam SQL i/lub pewnej denormalizacji, SQL musi "zobaczyć" ostatnie rekordy na tej liście , jeśli należą do góry, pod względem sortowania).

Ten ostatni fakt przemawia za posiadaniem tego samego zapytania do obu celów, odpowiednia lista może być przechowywana w tabeli tymczasowej. Ogólny proces polegałby na szybkim wyszukaniu rekordów N Item z ich szczegółami i natychmiastowym zwróceniu ich do aplikacji. Aplikacja może następnie uzyskać ajax-fashion listę znaczników w celu doprecyzowania. Ta lista byłaby generowana z zapytaniem podobnym do powyższego, gdzie podzapytanie jest zastępowane przez „wybierz * z tabeli tymczasowej”. Szanse są duże, że optymalizator SQL zdecyduje się posortować tę listę (w niektórych przypadkach), pozwólmy mu to zrobić, zamiast zgadywać ją i jawnie sortować.

Inną kwestią do rozważenia jest umieszczenie sprzężeń w tabeli ItemTagMap wewnątrz „zapytania sterującego”, a nie jak pokazano powyżej. Prawdopodobnie najlepiej to zrobić, zarówno ze względu na wydajność, jak i dlatego, że utworzy właściwą listę dla celu nr 2 (wyświetlanie strony elementów).

Opisane powyżej zapytanie/przepływ prawdopodobnie będzie się skalować dość dobrze, nawet na stosunkowo skromnym sprzęcie; wstępnie na pół miliona+ przedmiotów, przy ciągłym wyszukiwaniu przez użytkowników może do 10 na sekundę. Jednym z kluczowych czynników byłaby selektywność wstępnych kryteriów wyszukiwania.

Pomysły na optymalizację

  • [W zależności od typowych przypadków wyszukiwania i statystyk danych] sensowna może być denormalizacja poprzez przeniesienie (rzeczywiście zduplikowanie) niektórych pól Items do tabeli ItemTagMap. Szczególnie krótkie pola mogą być tam „mile widziane”.
  • Gdy dane rosną w ponad milionie elementów, możemy wykorzystać typowo silną korelację niektórych tagów (np. w SO, PHP często zawiera MySql, btw często bez powodu...) za pomocą różnych sztuczek. Na przykład wprowadzenie tagów „multi-Tag” może nieco bardziej skomplikować logikę wejściową, ale może również znacznie zmniejszyć rozmiar mapy.


-- „nic nie zostało powiedziane! --
Należy wybrać odpowiednią architekturę i optymalizacje w świetle rzeczywistych wymagań i efektywnego profilu statystycznego danych...



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak skonfigurować replikację źródła-repliki w MySQL?

  2. Jak sprawdzić wersję MySQL

  3. Generowanie encji z bazy danych

  4. Nieznana kolumna na liście pól

  5. Różnica między FIELD() i FIND_IN_SET() w MySQL