sql >> Database teknologi >  >> RDS >> Mysql

Hvordan implementerer man tagging-system svarende til SO i php/mysql?

Før vi går ind i for tidlig optimering tilstand, kan det være nyttigt at se på følgende forespørgselsskabelon. Om ikke andet kunne dette bruges som en baseline, som effektiviteten af ​​mulige optimeringer kan måles mod.

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

Underforespørgslen er "drivforespørgslen", dvs. den, der svarer til slutbrugerens indledende kriterier. (se nedenfor for detaljer om, hvordan denne forespørgsel, der kræves flere gange, kan passe ind i et overordnet optimeret flow) Kommenteret er JOIN på T1 (og muligvis T2, T3, når flere tags er valgt), og med WHERE-klausulen, den tilhørende kriterier. Disse er nødvendige, når brugeren vælger et bestemt tag, hvad enten det er som en del af den indledende søgning eller ved forfining. (Det kan være mere effektivt at placere disse joins og hvor-klausuler i underforespørgslen; mere om disse nedenfor)

Diskussion... "Køreforespørgslen" eller en variation deraf er nødvendig til to forskellige formål:

  • 1 for at give den komplette liste over ItemId, som er nødvendig for at opregne alle tilknyttede tags.

  • 2 for at angive de første N ItemId-værdier (N er den viste sidestørrelse) med det formål at slå op på varedetaljer i tabellen med varer.

Bemærk, at den komplette liste ikke behøver at blive sorteret (eller den kan have gavn af at sortere i en anden rækkefølge), hvorved den anden liste skal sorteres baseret på brugerens valg (f.eks. efter dato, faldende eller efter titel, alfabetisk stigende ). Bemærk også, at hvis der er en sorteringsrækkefølge påkrævet, vil omkostningerne ved forespørgslen indebære, at der skal håndteres den komplette liste (genert for ulige optimering af SQL selv og/eller nogle denormaliseringer, SQL skal "se" de sidste poster på denne liste , hvis de hører til i toppen, sorteringsmæssigt).

Dette sidstnævnte faktum er til fordel for at have den samme forespørgsel til begge formål, den tilsvarende liste kan gemmes i en midlertidig tabel. Det generelle flow ville være hurtigt at slå de øverste N-vareposter op med deres detaljer og returnere dette til applikationen på én gang. Applikationen kan derefter få ajax-fashion listen over tags til forbedringer. Denne liste vil blive fremstillet med en forespørgsel, der ligner den ovenfor, hvor underforespørgslen er erstattet af en "vælg * fra midlertidig tabel." Oddsene er gode for, at SQL-optimeringsværktøjet vil beslutte at sortere denne liste (i nogle tilfælde), lad os lade den gøre det, i stedet for at gætte den og sortere den eksplicit.

Et andet punkt at overveje er måske at bringe join(s) på ItemTagMap-tabellen inde i "drive-forespørgslen" i stedet for som vist ovenfor. Det er nok bedst at gøre det, både for ydeevne, og fordi det vil producere den rigtige liste til formålet #2 (visning af en side med elementer).

Forespørgslen/flowet beskrevet ovenfor vil sandsynligvis skalere ret godt, selv på relativt beskeden hardware; foreløbigt ind i 1/2 Million+ Items, med vedvarende brugersøgninger måske op til 10 pr. sekund. En af nøglefaktorerne ville være selektiviteten af ​​de indledende søgekriterier.

Optimeringsidéer

  • [Afhængig af de typiske søgetilfælde og af datastatistikken] kan det give mening at denormalisere ved at bringe (faktisk duplikere) nogle af Items felter til ItemTagMap-tabellen. Især korte felter kan være 'velkommen' der.
  • Efterhånden som dataene vokser i flere millioner elementer, kunne vi udnytte den typisk stærke korrelation af nogle tags (f.eks. i SO kommer PHP ofte med MySql, forresten ofte uden god grund...), med forskellige tricks. For eksempel kunne indførelsen af ​​"multi-tag" TagId'er gøre inputlogikken en smule mere kompliceret, men kunne også reducere kortstørrelsen betydeligt.


-- 'ingen sagt! --
Den passende arkitektur og optimeringer bør vælges i lyset af de faktiske krav og den effektive datastatistiske profil...



  1. Sådan opgraderes MySQL 5.5 til 5.6 på Ubuntu 14.04

  2. Sådan flytter du og slet feltet i MySQL

  3. Opdatering af Woocommerce-ordrer programmatisk

  4. Hvordan kan jeg lave en sammenhængende gruppe i MySQL?