Filter mit Zählern implementieren

8

Was ich erreichen möchte:

Ich entwickle Website mit einem Katalog von Produkten.
Dies ist ein normalisiertes Modell (vereinfacht) von Entitäten, die mit meiner Frage verwandt sind:

Es gibt also einige Produktmerkmale (wie Größe und Typ in diesem Beispiel), die alle vordefinierte Mengen von Werten haben (z. B. Größen 1, 2 und 3 und Typ kann 1, 2 oder 3 sein) um gleich zu sein, nur ein Beispiel.)).
Die Beziehung zwischen Produkt und jedem Merkmal ist "viele-zu-viele" - unterschiedliche Werte eines Merkmals schließen sich nicht gegenseitig aus.
Meine Aufgabe besteht darin, ein Formular zu erstellen, mit dem Benutzer Suchergebnisse anhand von Produktmerkmalen filtern können. Beispiel Screenshot:

Mehrfach überprüfte Werte eines Merkmals werden unter Verwendung der "AND" Logik gemischt, also wenn ich Größen eins und drei geprüft habe, benötige ich alle Produkte, die beide Größen haben (+ kann irgendwelche anderen Größen haben, die nicht wichtig sind, aber ausgewählte müssen anwesend sein).

Die Zahl in der Nähe jedes Werts des Features steht für die Menge der Produkte, die zurückgegeben wird, wenn der Benutzer diesen Wert gerade überprüft. Es ist also effektiv eine Anzahl von Produkten, die Filter "aktueller aktiver Filter + diesen einen Wert angewendet" erfüllen.

Wenn Benutzer einen Wert prüfen / deaktivieren, müssen Zähler unter Berücksichtigung des neuen "aktuellen Filters" aktualisiert werden.

Problem:

Wirklicher Anwendungsfall ist: ~ 200k Produkte, ~ 6 Features mit jeweils ~ 5-15 Werten.
Meine COUNT -Abfragen, (besonders mit einer anständigen Anzahl von ausgewählten Optionen) sind zu langsam, und um das Formular zu machen, brauche ich so viele dieser Werte, wie es Werte aller Filter gibt - insgesamt ergibt das eine inakzeptable Antwortzeit.

>

Was ich versucht habe:

  • Abfrage zum Abrufen der Ergebnisse:

    %Vor%

(Auswahl von Produkten mit den Größen 1, 2, 3 und 5 gleichzeitig).
Es vervollständigt in ~0.360 sec auf 120k Produkten, fast zeitgleich mit COUNT um es gewickelt. Und diese Abfrage erlaubt nicht mehr als ein Feature (aber ich könnte Werte aller Features in einer Tabelle platzieren).

  • Eine weitere Abfrage zum Abrufen des gleichen Satzes:

    %Vor%

Er wird in ~0.230 sec abgeschlossen (gleichzeitig mit dem Umbruch in COUNT ) und erlaubt auch nicht mehrere Features.
Es ist eine modifizierte Abfrage, die ich hier gefunden habe: Ссылка (zweite Abfrage in "Division mit einem Rest" -Teil).

  • Alternatives Schema:

Denormalisiertes Modell, wobei der Wert jedes Features eine boolesche Spalte in der Products-Tabelle ist.
Die Abfrage ist hier offensichtlich:

%Vor%

Seltsam und schwieriger im Code der Anwendung zu verwalten, wird jedoch in ~0.056 sec abgeschlossen, wenn COUNT -ing.

Keine dieser Methoden ist an sich akzeptabel, weil sie etwa 30 mal multipliziert wird (um alle Zähler in Form zu füllen), was eine unangemessene Antwortzeit ergibt.

  • Caching und Vorberechnung von Daten in der DB werden nur ein paar Mal am Tag aktualisiert (wie vielleicht sogar 2), daher könnte ich wahrscheinlich Zählungen für alle Filterkombinationen vorberechnen, wenn Daten aktualisiert werden (ich habe die notwendige Zeit nicht gemessen, um ehrlich zu sein) , aber es funktioniert sowieso nicht - Suchformular hat Felder mit willkürlichen Werten (wie Min / Max Preis und Textsuche nach dem Produktnamen), für die ich nicht vorberechnen kann.

  • Laden Sie Zähler in Form dynamisch Render Form, aber Zahlen durch AJAX, so dass Benutzer in der Lage sein würde, Seite zu sehen, und dann, nach ziemlich langen Warten, Zahlen. Dies ist mein letzter Gedanke, aber es scheint für mich eine schlechte Dienstqualität zu sein (vielleicht ist es schlimmer als gar keine Zähler).

Ich stecke fest. Irgendwelche Hinweise? Vielleicht sehe ich kein größeres Bild? Ich würde mich sehr über jeden Rat freuen.

AKTUALISIEREN : Wenn wir Zähler vergessen haben, was ist die effektivste und gebräuchlichste Methode (Abfrage), um Ergebnisse mit solchen Filtern zu erhalten (oder was mache ich falsch)? Wie "Finden Sie Post mit allen angeforderten Tags" -Modell, das ist äquivalent. Ich vermute, dass es schneller als meine 0.230 sec (Abfrage # 2) sein kann, unter Berücksichtigung der kleinen (?) Anzahl von Zeilen für MySQL.

    
Oleg Arkhipov 12.01.2017, 07:23
quelle

1 Antwort

1

Sie können

  1. Erstellen Sie eine Tabelle, in der alle möglichen Kombinationen gespeichert werden (product_id & lt; & gt; size_id & lt; & gt; type_id)
  2. Aktualisieren Sie diese Tabelle, wenn der Administrator Änderungen am Produkt vom Backend aus vornimmt (vorausgesetzt, es wird eine Backend-Verwaltung geben)
  3. Im Frontend verwenden Sie für Filter diese Tabelle anstelle von Produkttabellen und extrahieren Produkt-IDs, sobald die Filterabfrage ausgelöst wurde
  4. Sobald Sie eine Liste mit Produkt-IDs für das Ergebnis erstellt haben, können Sie die tatsächlichen Daten mithilfe dieser Produkt-IDs abrufen

Ich habe das schon früher benutzt, und es hat für mich funktioniert, Sie können zuerst eine Tabelle erstellen und versuchen, eine Abfrage auszuführen, um die Antwortzeit zu überprüfen.

Hoffe, das hilft.

    
Patrick R 18.01.2017 05:33
quelle

Tags und Links