Frage

Ich arbeite an einer Abfrage für eine Nachrichtenseite, auf der FeaturedContent zur Anzeige auf der Haupthomepage gefunden wird. Auf diese Weise gekennzeichnete Inhalte werden als "FeaturedContent" gekennzeichnet und von "homepage" in einer vorgestellten Tabelle sortiert. Ich habe derzeit die gewünschte Ausgabe, aber die Abfrage wird in mehr als 3 Sekunden ausgeführt, was ich reduzieren muss. Wie optimiert man eine Abfrage wie die folgende?

BEARBEITEN: Die Ansicht wurde jede Minute wie vorgeschlagen auf 0,4 Sekunden materialisiert:

SELECT f.position, s.item_id, s.item_type, s.title, s.caption, s.date
FROM live.search_all s 
INNER JOIN live.tags t 
ON s.item_id = t.item_id AND s.item_type = t.item_type AND t.tag = 'FeaturedContent' 
LEFT OUTER JOIN live.featured f 
ON s.item_id = f.item_id AND s.item_type = f.item_type AND f.feature_type = 'homepage'
ORDER BY position IS NULL, position ASC, date

Hiermit werden alle Funktionen der Startseite in der angegebenen Reihenfolge zurückgegeben, gefolgt von anderen nach Datum geordneten Inhalten.
Die Erklärung sieht folgendermaßen aus:

|-id---|-select_type-|-table-|-type---|-possible_keys---------|-key--------|-key_len-|-ref---------------------------------------|-rows--|-Extra-------------------------------------------------------------|
|-1----|-SIMPLE------|-t2----|-ref----|-PRIMARY,tag_index-----|-tag_index--|-303-----|-const-------------------------------------|-2-----|-Using where; Using index; Using temporary; Using filesort;--------|
|-1----|-SIMPLE------|-t-----|-ref----|-PRIMARY---------------|-PRIMARY----|-4-------|-newswires.t2.id---------------------------|-1974--|-Using index-------------------------------------------------------|
|-1----|-SIMPLE------|-s-----|-eq_ref-|-PRIMARY, search_index-|-PRIMARY----|-124-----|-newswires.t.item_id,newswires.t.item_type-|-1-----|-------------------------------------------------------------------|
|-1----|-SIMPLE------|-f-----|-index--|-NULL------------------|-PRIMARY----|-190-----|-NULL--------------------------------------|-13----|-Using index-------------------------------------------------------|

Und das Profil lautet wie folgt:

|-Status---------------|-Time-----|
|-starting-------------|-0.000091-|
|-Opening tables-------|-0.000756-|
|-System lock----------|-0.000005-|
|-Table lock-----------|-0.000008-|
|-init-----------------|-0.000004-|
|-checking permissions-|-0.000001-|
|-checking permissions-|-0.000001-|
|-checking permissions-|-0.000043-|
|-optimizing-----------|-0.000019-|
|-statistics-----------|-0.000127-|
|-preparing------------|-0.000023-|
|-Creating tmp table---|-0.001802-|
|-executing------------|-0.000001-|
|-Copying to tmp table-|-0.311445-|
|-Sorting result-------|-0.014819-|
|-Sending data---------|-0.000227-|
|-end------------------|-0.000002-|
|-removing tmp table---|-0.002010-|
|-end------------------|-0.000005-|
|-query end------------|-0.000001-|
|-freeing items--------|-0.000296-|
|-logging slow query---|-0.000001-|
|-cleaning up----------|-0.000007-|

Ich bin neu im Lesen der EXPLAIN-Ausgabe, daher bin ich mir nicht sicher, ob ich eine bessere Bestellung zur Verfügung habe oder etwas ziemlich Einfaches, das getan werden könnte, um diese zu beschleunigen.

Die Tabelle search_all ist die materialisierte Ansichtstabelle, die regelmäßig aktualisiert wird, während die Tags und vorgestellten Tabellen Ansichten sind. Diese Ansichten sind nicht optional und können nicht umgangen werden.

In der Tags-Ansicht werden Tags und eine relationale Tabelle kombiniert, um eine Liste der Tags nach item_type und item_id wiederherzustellen. Die anderen Ansichten sind jedoch alle einfache Ansichten einer Tabelle.

BEARBEITEN: Bei der materialisierten Ansicht scheint der größte Engpass der Schritt "In temporäre Tabelle kopieren" zu sein. Ohne Bestellung der Ausgabe dauert es 0,0025 Sekunden (viel besser!), Aber die endgültige Ausgabe muss bestellt werden. Gibt es eine Möglichkeit, die Leistung dieses Schritts zu verbessern oder ihn zu umgehen?

Entschuldigung, wenn die Formatierung schwer zu lesen ist, bin ich neu und unsicher, wie sie regelmäßig durchgeführt wird.
Danke für Ihre Hilfe! Wenn noch etwas benötigt wird, lass es mich wissen!

BEARBEITEN: Tabellengrößen als Referenz:
Tag-Beziehungen: 197.411
Tags: 16.897
Geschichten: 51.801
Bilder: 28.383
Videos: 2.408
Hervorgehoben: 13

War es hilfreich?

Lösung

Ich denke, die Optimierung Ihrer Abfrage allein ist nicht sehr nützlich. Der erste Gedanke ist, dass der Beitritt zu einer Unterabfrage, die selbst aus UNIONs besteht, allein ein doppelter Engpass für die Leistung ist.

Wenn Sie die Option haben, Ihre Datenbankstruktur zu ändern, würde ich vorschlagen, die 3 Tabellen stories, images und videos zu einer zusammenzuführen, wenn sie, wie es aussieht, sehr ähnlich sind (indem Sie ihnen einen type ENUM('story', 'image', 'video') hinzufügen), um sie zu unterscheiden die Aufzeichnungen; Dies würde sowohl die Unterabfrage als auch die Vereinigung entfernen.

Es sieht auch so aus, als würden Ihre Ansichten zu stories und videos kein indiziertes Feld zum Filtern von Inhalten verwenden. Fragen Sie eine indizierte Spalte ab?

Es ist ein ziemlich kniffliges Problem, ohne Ihre vollständige Tabellenstruktur und die Aufteilung Ihrer Daten zu kennen!

Eine weitere Option, bei der keine Änderungen an Ihrer vorhandenen Datenbank vorgenommen werden müssen (insbesondere wenn diese bereits in Produktion ist), besteht darin, diese Informationen in einer anderen Tabelle zu "zwischenspeichern", die regelmäßig durch einen Cron-Job aktualisiert wird.

Das Caching kann auf verschiedenen Ebenen erfolgen, entweder für die vollständige Abfrage oder für Teile davon (unabhängige Ansichten oder die drei in einer einzelnen Cache-Tabelle zusammengeführten Gewerkschaften usw.)

Die Realisierbarkeit dieser Option hängt davon ab, ob es akzeptabel ist, leicht veraltete Daten anzuzeigen oder nicht. Dies ist möglicherweise nur für einige Teile Ihrer Daten akzeptabel, was bedeuten kann, dass Sie nur einen Teil der an der Abfrage beteiligten Tabellen / Ansichten zwischenspeichern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top