Optimalizálása lekérdezéseket a következő és az előző elem

szavazat
28

I am looking for a legjobb módja, hogy megkapd az előző és következő bejegyzések egy rekord nélkül fut teljes lekérdezést. Van egy teljesen megvalósított megoldás helyett, és szeretné tudni, hogy van-e jobb megközelítés, hogy ezt odakint.

Tegyük fel, hogy építünk egy weboldal egy fiktív zöldséges. Amellett, hogy a HTML-oldalak, minden héten, azt akarja, hogy közzéteszi az akciók az ő helyén. Azt akarja azokat az ajánlatokat, hogy tartózkodjon a tényleges adatbázis tábla, és a felhasználók, hogy képes rendezni az ajánlatokat három módon.

Minden elem is van, hogy egy részletes oldal, több, szöveges információk a megrendelésről és a „korábbi” és „next” gomb. Az „előző” és „következő” gombokkal kell mutatni, hogy a szomszédos bejegyzések függően válogatás a felhasználó választotta a listán .

alt szöveg http://www.pekkagaiser.com/stuff/Sort.gif?

Nyilvánvaló, hogy a „következő” gombot „Paradicsom, I. osztály” lehet „Alma, 1. osztály” az első példa, „körte, I. osztályú” a második, és egyik sem a harmadik.

A feladat a részletes leírást , hogy meghatározzák a következő és az előző tételek nélkül fut a lekérdezés minden alkalommal , a sorrend a lista, mint az egyetlen rendelkezésre álló információk (Mondjuk kap, hogy egy GET paraméter ?sort=offeroftheweek_price, és figyelmen kívül hagyja a biztonsági következmények) .

Nyilvánvaló, hogy csak múló az azonosítók a következő és az előző elemek, mint a paraméter az első megoldás, ami eszébe jut. Végtére is, mi már tudjuk, az azonosító ezen a ponton. De ez nem egy lehetőség van - ez is működne ez a leegyszerűsített példa, de nem sok a valós használati esetek.

A jelenlegi megközelítés én CMS használ valami, amit nevű „válogatás cache”. Ha egy lista van betöltve, azt tárolja a tételt pozíciók nyilvántartásait a táblát sortingcache.

name (VARCHAR)             items (TEXT)

offeroftheweek_unsorted    Lettuce; Tomatoes; Apples I; Apples II; Pears
offeroftheweek_price       Tomatoes;Pears;Apples I; Apples II; Lettuce
offeroftheweek_class_asc   Apples II;Lettuce;Apples;Pears;Tomatoes

Nyilvánvaló, hogy az itemsoszlop valóban lakott numerikus azonosítók.

A részletes oldal, most elérheti a megfelelő sortingcacherekordot, letölti az itemsoszlop, felrobban, keressük meg az aktuális elem azonosítója és visszatér az előző és a következő szomszéd.

array(current   => Tomatoes,
      next      => Pears,
      previous  => null
      );

Ez nyilvánvalóan költséges, munkák korlátozott rekordok száma csak teremt redundáns adatok, de tételezzük fel, hogy a valós világban, a lekérdezés, hogy megteremtse a listákat nagyon drága (ez), fut minden részletében nézet ki a kérdésre, és néhány caching van szükség.

Kérdéseim:

  • Gondolod, hogy ez egy jó gyakorlat, hogy megtudja, a szomszédos bejegyzések változtatására lekérdezés megrendeléseket?

  • Tudod jobb gyakorlatok a teljesítmény és az egyszerűség? Tud valamit, ami ezt teljesen elavult?

  • A programozás elmélet, van egy név erre a problémára?

  • A neve „Válogató cache” megfelelő és érthető, hogy ez a technika?

  • Vannak olyan elismert, közös mintákat, hogy megoldja ezt a problémát? Mit hívják?

Megjegyzés: A kérdésem nem kiépíteni a listából, vagy hogyan kell megjeleníteni a részletes nézetben. Ezek csak példák. A kérdésem az alapvető funkciókat meghatározásának szomszédok egy rekordot, amikor újra lekérdezés lehetetlen, és a leggyorsabb és legolcsóbb módja annak, hogy ott van.

Ha valami nem világos, kérem, hagyjon egy megjegyzést, és azt fogja tisztázni.

Kezdve a bounty - talán van még egy kis info erről odakint.

A kérdést 22/02/2010 12:06
a forrás felhasználó
Más nyelveken...                            


11 válasz

szavazat
-3

Tehát van két feladat:

  1. építeni rendezett listáját tételek (SELECT-más ORDER BY)
  2. mutatnak egyes tételek részleteit (SELECT részleteket adatbázist lehetséges caching).

Mi a probléma?

PS: ha rendezett lista lehet, hogy túl nagy akkor csak meg kell PÁGER alkalmassága végrehajtani. Lehetne más megvalósítások, pl érdemes felvennie a „LIMIT 5” lekérdezés, és a „Show következő 5” gombot. Ha ezt a gombot megnyomjuk, állapot, mint a „WHERE ár <0,89 LIMIT 5” hozzá.

Válaszolt 22/02/2010 15:04
a forrás felhasználó

szavazat
16

Itt van egy ötletem. Lehet tehermentesíti a drága művelet egy olyan frissítést, amikor a fűszeres insert / update új ajánlatok helyett, ha a végfelhasználó választja ki az adatokat, hogy megtekinthesse. Ez úgy tűnhet, mint egy nem dinamikus módon lehet kezelni a fajta adat, de lehet, hogy növeli a sebességet. És, mint tudjuk, mindig van egy kompromisszumot a teljesítmény és egyéb kódolási tényezők.

Hozzon létre egy táblázatot, hogy tartsa a következő és az előző minden ajánlat és az egyes rendezési opciót. (Vagy lehet tárolni ezt az ajánlatot asztalra, ha mindig van három fajta lehetőség - lekérdezés sebességét egy jó ok arra, hogy az adatbázis denormalizálni)

Tehát meg kellett volna ezeket az oszlopokat:

  • Rendezés típusa (szétválogatott, Ár, Class és Ár termék)
  • ajánlat sorszáma
  • Előző ID
  • Következő ID

Ha a részletes információkat az ajánlat részletes oldal lekérdezi az adatbázisból, a NextID és PrevID része lenne az eredmény. Tehát csak akkor kell egy lekérdezést az egyes részletes oldal.

Minden alkalommal, amikor egy ajánlat kerül be, frissíteni vagy törölni, akkor azt kell futtatni egy folyamat, amely érvényesíti a integritását / pontosságát sorttype asztalra.

Válaszolt 22/02/2010 20:20
a forrás felhasználó

szavazat
1

Nem vagyok benne biztos, hogy jól értettem van, így ha nem, csak mondd meg;)

Mondjuk, hogy az adottságai a lekérdezést a rendezett listát, és a jelenlegi offset a listán, vagyis van egy $queryés egy $n.

Egy nagyon kézenfekvő megoldás, hogy minimalizáljuk a lekérdezések, az lenne, hogy hívni az összes adat egyszerre:

list($prev, $current, $next) = DB::q($query . ' LIMIT ?i, 3', $n - 1)->fetchAll(PDO::FETCH_NUM);

Ez a kijelentés gyűjti össze az előző, a jelenlegi és a következő elemeket az adatbázisból az aktuális rendezési sorrend, és hozza a hozzá tartozó információkat a megfelelő változókat.

De mivel ez a megoldás túl egyszerű, azt feltételezzük, félreértettem valamit.

Válaszolt 07/02/2011 20:31
a forrás felhasználó

szavazat
2

Elegem rémálmok ezzel egyet is. A jelenlegi megközelítés tűnik a legjobb megoldásnak még listáit 10k terméket. Gyorstárazott azonosítói a lista nézetben a http ülésen, majd használja, hogy a kijelzésére (személyre aktuális felhasználó) előző / következő. Ez jól működik, különösen akkor, ha túl sok szempontból szűrhetők és rendezhetők a kezdeti tételek listáját helyett csak 3
is tárolja az egész azonosítók listája kapsz megjelenítéséhez "you are at X out of Y"használhatóság fokozása szöveget.
JIRA előző / következő

By the way, ez az, amit JIRA nem is.

Ahhoz, hogy közvetlenül válaszolni a kérdésekre:

  • Igen ez jó gyakorlat, mert mérleg nélkül felvett kód bonyolultságát, ha a szűrő / válogatás és elemtípusnál varjú bonyolultabb. Én használ ez a termelési rendszer 250k cikkek „végtelen” filter / fajta eltérések. Vágása gyorsítótárazható azonosítókat 1000 is van lehetőség, mivel a felhasználó valószínűleg soha nem kattint előző vagy a következő több mint 500-szor (Majd valószínűleg megy vissza, és finomítani a keresést, vagy tördeli).
  • Nem tudom, hogy egy jobb út. De ha a fajta, ahol korlátozott, és ez egy nyilvános oldalon (nincs http ülés) akkor azt valószínűleg denormalizálni.
  • Nemtom.
  • Igen, válogatás cache jól hangzik. Az én projektben hívom, hogy „az előző / következő keresési eredmények” vagy „navigációs eredményt”.
  • Nemtom.
Válaszolt 07/02/2011 21:04
a forrás felhasználó

szavazat
2

Általában azt denormalizálni az adatokat az indexeket. Ezek tárolhatók ugyanabban a sorban, de én szinte mindig letölteni én eredmény azonosítókat, majd egy külön utat az adatokat. Ez teszi cache-adatok nagyon egyszerű. Ez nem olyan fontos, a PHP, ahol a várakozási idő csekély, és a sávszélesség magas, de egy ilyen stratégia nagyon hasznos, ha van egy hosszú várakozási idő, az alacsony sávszélesség-felhasználás, mint például az AJAX weboldal, ahol sok a hely teszi a JavaScript.

Mindig cache a listákat az eredmények, és az eredmények önmagukban külön-külön. Ha bármi befolyásolja az eredményeket egy listában lekérdezést, a cache a lista eredménye frissül. Ha bármi befolyásolja az eredmények önmagukban, ezek különösen eredmények frissül. Ez lehetővé teszi, hogy frissítsem vagy egy, anélkül, hogy regenerálódni mindent, ami a hatékony cache-t.

Mivel a listákat eredmények ritkán változnak, generálja a listákat ugyanabban az időben. Ez lehet, hogy a kezdeti válasz kissé lassabb, de ez egyszerűsíti cache frissítő (az összes listát kap tárolni egyetlen cache bejegyzést).

Mert van a teljes listát a gyorsítótárban, akkor egyszerűen meg lehet találni a szomszédos elemeket anélkül feleleveníti az adatbázisban. Ha szerencsénk van, az adatokat a fenti tételek is tárolásra kerülnek. Ez különösen akkor hasznos, amikor válogatás adatok JavaScript. Ha már van egy példánya a gyorsítótárban az ügyfél, én is igénybe azonnal.

Válaszolni a kérdésekre konkrétan:

  • Igen, ez egy fantasztikus ötlet, hogy megtudja, a szomszédok idő előtt, vagy bármilyen információt az ügyfél valószínűleg elérni a következő, különösen, ha a költség alacsony, és most a költség újraszámolja magas. Akkor ez csak egy kompromisszum extra előkalkulációs és tárolási sebesség függvényében.
  • Ami a teljesítményt és az egyszerűség, ne árukapcsolás dolgokat együtt, amelyek logikailag különböző dolog. Indexek és az adatok különböző, valószínűleg meg kell változtatni különböző időpontokban (pl, hogy egy új nullapont hatással lesz az indexek, de nem a meglévő adatok alapján), és így kell elérni külön-külön. Ez lehet kevésbé hatékony, egyetlen szálon szempontból, de minden alkalommal döntetlen valamit együtt, akkor elveszíti cache-hatékonyság és asychronosity (a kulcs a méretezés asychronosity).
  • A kifejezés a szerzés adatok idő előtt előtöltésről. Előtöltés megtörténhet idején hozzáférés vagy a háttérben, de még mielőtt az előre letöltött adatok ténylegesen szükség van. Hasonlóképpen előre számítás. Ez egy trade-off cégek most, tárolási költség, és a költség, hogy ha szükséges.
  • „Az osztályozás cache” találó név.
  • Nem tudom.

Továbbá, ha gyorsítótár dolgokat, gyorsítótár őket a legáltalánosabb szinten lehetséges. Néhány dolog lehet felhasználó-specifikus (például eredménye a keresésnek), ahol mások is felhasználó agnosztikus, mint például a böngészés egy katalógust. Mindkét részesülhet cache-t. A katalógus lekérdezés lehet gyakori, és mentse egy kicsit minden alkalommal, és a keresési lekérdezés lehet drága és menteni egy csomó egy párszor.

Válaszolt 09/02/2011 08:00
a forrás felhasználó

szavazat
0

Van annyi módja van ennek, hogy a bőr a közmondásos macska. Tehát itt van egy pár enyém.

Ha az eredeti lekérdezés drága, ami azt mondja, hogy igen, akkor hozzon létre egy másik táblázatot esetleg egy memória asztal megtölteni azt az eredmények a drága és csak ritkán fut fő lekérdezés.

Ez a második tábla lehetne kérdezni minden nézet és a rendezési olyan egyszerű, mint a beállítás a megfelelő sorrend.

Mivel szükséges, újra benépesítik a második táblázat eredményeit az első tábla, és így megőrizze az adatokat friss, de használatának minimalizálásával a drága lekérdezés.

Másik megoldás, ha el akarjuk kerülni, még csatlakozni a db akkor is tárolja az összes adatot egy PHP tömb, és tárolja a memcached. ez lenne nagyon gyors, és feltéve, hogy a listák nem voltak túl nagy lenne erőforrás-hatékony. és könnyen válogatni.

DC

Válaszolt 11/02/2011 05:19
a forrás felhasználó

szavazat
0

Alapvető feltételezések:

  • Akciós vannak heti
  • Mi várható a helyszínen változtatni ritkán ... valószínűleg naponta?
  • Mi lehet szabályozni a frissítéseket az adatbázis éter egy API vagy válaszolni keresztül kiváltó

Ha a hely változik naponta, azt javaslom, hogy minden oldal statikusan generált egy éjszakán át. Egy lekérdezés minden sort-order végigmegy, és teszi a kapcsolódó oldalak. Még ha vannak is dinamikus elemeket, esély, hogy akkor foglalkozni, hogy felveszi a statikus oldal elemek. Ez biztosítja az optimális oldal szolgáltatást és nem adatbázis terhelést. Sőt, ha esetleg generálni külön oldalakon és prev / next elemeket, amelyek szerepelnek az oldalakra. Ez lehet őrültebb 200 módokon rendezheti, de 3 vagyok nagy rajongója is.

?sort=price
include(/sorts/$sort/tomatoes_class_1)
/*tomatoes_class_1 is probably a numeric id; sanitize your sort key... use numerics?*/

Ha valamilyen okból ez nem valósítható meg, azt igénybe megjegyezni. Memcache népszerű ez a fajta dolog (szójáték!). Ha valami van nyomva az adatbázishoz, akkor kiadja a ravaszt, hogy frissítse a gyorsítótárat a helyes értékeket. Ehhez ugyanúgy akkor, ha például, ha a frissített elem létezett 3 kapcsolt listák - átszerkeszthesse megfelelő (this.next.prev = this.prev, stb.) Attól, hogy mindaddig, amíg a cache nem túltöltés, akkor húzza egyszerű értékek memóriába elsődleges kulcs divat.

Ez a módszer lesz néhány extra kódolást a választó és frissítés / betét módszerek, de legyen elég minimális. A végén, akkor meg kell keresi fel [id of tomatoes class 1].price.next. Ha ez a kulcs a gyorsítótár, arany. Ha nem, helyezze cache és a kijelző.

  • Gondolod, hogy ez egy jó gyakorlat, hogy megtudja, a szomszédos bejegyzések változtatására lekérdezés megrendeléseket? Igen. Bölcs dolog, hogy végre meg-Aheads a várható következő kéréseket.
  • Tudod jobb gyakorlatok a teljesítmény és az egyszerűség? Tud valamit, ami ezt teljesen elavult? Remélhetőleg a fenti
  • A programozás elmélet, van egy név erre a problémára? Optimalizálás?
  • A neve „Válogató cache” megfelelő és érthető, hogy ez a technika? Nem tudom, egy meghatározott megfelelő nevet. Ez caching, ez egy cache a fajta, de nem vagyok benne biztos, hogy azt mondja, hogy van egy „válogatás cache” lenne közvetíteni azonnali megértést.
  • Vannak olyan elismert, közös mintákat, hogy megoldja ezt a problémát? Mit hívják? Gyorsítótár?

Bocs én farok válaszok fajta haszontalan, de azt hiszem, a narratív megoldások nagyon hasznos.

Válaszolt 11/02/2011 18:13
a forrás felhasználó

szavazat
0

Meg tudná menteni a sorszámok a megrendelt listákat nézetek , és akkor éri el a korábbi és a következő elemeket a listában (current_rownum-1) és (current_rownum + 1) sorban számokat.

Válaszolt 12/02/2011 14:01
a forrás felhasználó

szavazat
0

A probléma / datastructur nevű kétirányú grafikont, vagy meg tudná mondani, hogy van több kapcsolt listák.

Ha úgy gondolja, hogy ez egy láncolt lista, akkor is csak mezőket a terméket táblázat minden válogatás és prev / next gomb. De a DB személy meg fog ölni, hogy ez olyan, mint a GOTO.

Ha úgy gondolja, hogy ez egy (két) irányított gráf, akkor menjen el Jessica választ. A fő gond az, hogy annak érdekében, frissítések drágák műveleteket.

 Item Next Prev
   A   B     -
   B   C     A
   C   D     B
   ...

Ha megváltoztatja az egyik példány helyzetben az új rendhez A, C, B, D, akkor kell frissíteni 4 sor.

Válaszolt 13/02/2011 02:20
a forrás felhasználó

szavazat
4

Van egy ötletem, némileg hasonlít Jessica. Azonban ahelyett, tárolása linkek az előző és következő sort terméket, akkor tárolja a rendezés minden fajta típus. Ahhoz, hogy megtalálja az előző vagy a következő rekordra, csak kap sorában SortX = currentSort ++ vagy SortX = currentSort--.

Példa:

Type     Class Price Sort1  Sort2 Sort3
Lettuce  2     0.89  0      4     0
Tomatoes 1     1.50  1      0     4
Apples   1     1.10  2      2     2
Apples   2     0.95  3      3     1
Pears    1     1.25  4      1     3

Ez a megoldás így nagyon rövid lekérdezési időt, és azt, hogy kevesebb helyet, mint Jessica ötlete. Azonban biztos vagyok benne, rájössz, a költségek frissítése egyik adatsor is lényegesen magasabb, hiszen meg kell újraszámolni, és tárolja az összes rendezési sorrend. De mégis, a helyzettől függően, ha adatfrissítések ritkák és különösen akkor, ha mindig történik ömlesztve, akkor ez a megoldás lenne a legjobb.

azaz

once_per_day
  add/delete/update all records
  recalculate sort orders

Remélem, ez hasznos.

Válaszolt 13/02/2011 03:30
a forrás felhasználó

szavazat
0

Elnézést, ha félreértettem, de azt hiszem, meg akarja őrizni a rendezett lista közötti felhasználó hozzáfér a szerverhez. Ha igen, a válasz lehet, feküdjön a caching stratégia és technológiák helyett adatbázis lekérdezés / séma optimalizálás.

Saját megközelítés lenne sorosításához () a tömb egyszer az első letöltött, majd gyorsítótár, hogy egy külön tároló terület; legyen szó akár memcached / APC / merevlemez / MongoDB / stb, és megtartja a cache helyét adatai minden felhasználó egyénileg keresztül session adat. A tényleges tárolási backend természetesen függ a méret a tömb, amit nem megy be legrészletesebben, de memcached mérlegek nagy több szerverre és mongo még tovább valamivel nagyobb késleltetésű költség.

Ön még nem jelzi, hogy hány sort permutáció van a valós világban; pl van szüksége, hogy cache-külön listákat egy felhasználó, vagy tud globálisan gyorsítótár sort permutáció majd kiszűrni, amit nem kell keresztül PHP ?. A példában adsz, azt egyszerűen gyorsítótár mindkét módosulata és tárolja a kettő közül melyik szükséges, az I. unserialize () a session adat.

Amikor a felhasználó visszatér a helyszínre, ellenőrizze a Time To Live értéke a tárolt adatokat, és újra használni, ha továbbra is érvényes. Én is van egy ravaszt futó INSERT MELLŐZ / UPDATE / DELETE az akciók, hogy egyszerűen beállít egy timestamp mezőt külön táblázatban. Ez azonnal jelzi, hogy a gyorsítótár állott, és a lekérdezés szükséges, hogy újra futni egy nagyon alacsony költségű lekérdezés. A nagy dolog csak a ravaszt, hogy egy egységes területen az, hogy nincs szükség aggódnia metszés régi / redundáns értékeket ki, hogy a táblázatban.

Függetlenül attól, hogy ez alkalmas lenne függ a mérete az adatok visszaadás, hogy milyen gyakran módosították, és milyen caching technológiák állnak rendelkezésre a szerveren.

Válaszolt 13/02/2011 15:47
a forrás felhasználó

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more