Frage

Ich brauche optimieren Sie die folgende Abfrage:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM blogposts
JOIN articles ON articles.blogpost_id = blogposts.id
WHERE blogposts.deleted = 0
AND blogposts.title LIKE '%{de}%'
AND blogposts.visible = 1
AND blogposts.date_published <= NOW()
ORDER BY blogposts.date_created DESC
LIMIT 0 , 50

ERKLÄREN Sie WÄHLEN, gibt mir das folgende Ergebnis:

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE articles ALL blogpost_id NULL NULL NULL 6915 Using temporary; Using filesort
1 SIMPLE blogposts eq_ref PRIMARY PRIMARY 4 articles.blogpost_id 1 Using where

Warum muss es zuerst den Artikel und dann die Beiträge?Ist es, weil die Beiträge haben mehr Einträge?Und wie kann ich die Abfrage so, dass die articlepost können einen index verwenden?

Update: Ein index ist auf Artikel.date_created.Entfernen der Beiträge.Titel WIE Zustand und die date_published <= JETZT() tut nichts.

Wenn ich mit dem entfernen des "Artikel.id artikelid"es kann die blogpost_id-Index für Artikel, die...Klingt seltsam für mich, weiß jemand warum?(weil ich wirklich brauchen es..)

Die neue erklären sieht aus wie diese:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  articles    index blogpost_id blogpost_id    4    NULL    6915    Using index; Using temporary; Using filesort
1   SIMPLE  blogposts   eq_ref  PRIMARY PRIMARY 4   articles.blogpost_id    1   Using where
War es hilfreich?

Lösung

Ich nahm einen genaueren Blick auf die Abfrage, und Sie könnten in der Lage sein, um die Neugestaltung es.Hier ist was ich meine:

Der GRENZWERT 0,50 Teil der Abfrage zu haben scheint, beschäftigt in der letzten Abfrage.

Verbessern Sie das layout der Abfrage, indem Sie Folgendes tun:

Schritt 1) Erstellen Sie eine inline-Abfrage zu sammeln, die nur Tasten.In diesem Fall ist die id für Beiträge.

Schritt 2) Impose any WHERE, ORDER BY und GROUP BY-Klauseln auf die inline-Abfrage bringen die Schlüssel.

Schritt 3) Impost die LIMIT-Klausel, die als letzter Schritt der Herstellung der inline-Abfrage.

Schritt 4) nehmen Sie die inline-Abfrage mit der Artikel-Tabelle in dem Fall müssen Sie zusätzliche Spalten aus Beitrag als blostpost temptable

Schritt 5) nehmen Sie diese neuen blogpost temptable mit der Artikel-Tabelle.

Die Schritte 1-3 soll temptable mit genau 50 Zeilen und enthalten die Blog-id.Führen Sie dann alle Verknüpfungen tot zuletzt.

Mit diese Schritte, die in Bezug auf Ihre ursprüngliche Abfrage, sollten Sie diese:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
  SELECT B.*
  FROM
  (
    SELECT id FROM blogposts
    WHERE date_published <= NOW()
    AND deleted = 0 AND visible = 1
    AND title LIKE '%{de}%'
    ORDER BY date_created DESC
    LIMIT 0,50
  ) A
  INNER JOIN blogposts B USING (id)
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id;

Da Sie bearbeitet die Frage und erklärte, dass Sie entfernen MÖCHTEN, nun Ihre Abfrage sollte Aussehen wie dieses:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
  SELECT B.*
  FROM
  (
    SELECT id FROM blogposts
    WHERE date_published <= NOW()
    AND deleted = 0 AND visible = 1
    ORDER BY date_created DESC
    LIMIT 0,50
  ) A
  INNER JOIN blogposts B USING (id)
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id;

In der phrase [die Dinge weggelassen], wenn Sie nicht benötigen, alles von Artikel zu anderen als den Schlüssel, dann Ihre Abfrage sollte wie folgt Aussehen:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
  SELECT id FROM blogposts
  WHERE date_published <= NOW()
  AND deleted = 0 AND visible = 1
  ORDER BY date_created DESC
  LIMIT 0,50
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id;

CAVEAT

Stellen Sie sicher, dass Sie einen index erstellen, um die Spalten gelöscht, sichtbar, und date_created wie folgt:

ALTER TABLE blogposts ADD INDEX deleted_visible_date_created (deleted,visible,date_created);

Probieren Sie es aus !!!

Andere Tipps

Ihr Ort blogposts.title LIKE '%{de}%' führt zu einem vollständigen Tischscan auf der Blogeinträge Tisch. Es ist wahrscheinlich, dass MySQL -Zahlen 6915 Artikel effizienter scannen.

Um es zu verbessern, können Sie einen Index hinzufügen Blogeinträge Verwendung der date_created oder date_published und fügen Sie einen Bereich hinzu, um die Bedingung zu erhalten (etwas anderes als <= jetzt ())

Und blogposts.title wie '%{de}%' - nutzlos für die Optimierung (führende Wildkarte)

Wobei blogposts.deleted = 0 und blogposts.vissible = 1 - Yuck: Wenn sie nicht angezeigt werden sollten, bringen Sie sie aus der Tabelle.

Und blogposts.date_published <= now () order by blogposts.date_created Desc Limit 0, 50 - Dies führt dazu, dass der Index benötigt wird (Datum_Published) (jedoch wie und Flags können verhindern, dass dieser Index verwendet wird.)

Bitte geben Sie die Tabelle erstellen erstellen ...; Tabellenstatus anzeigen ...;

Vielen Dank :)

Ich habe es versucht und herausgefunden, dass tatsächlich Ihr letzter Kommentar zum Index das war, was ich brauchte. Manchmal ist es nur eine kleine Verbesserung, die benötigt wird ...;) Vergleich:

Alte Abfrage:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM blogposts
JOIN articles ON articles.blogpost_id = blogposts.id
WHERE blogposts.deleted = 0
AND blogposts.title LIKE '%{de}%'
AND blogposts.visible = 1
AND blogposts.date_published <= NOW()
ORDER BY blogposts.date_created DESC
LIMIT 0 , 50

Neue Abfrage:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
    SELECT B.*
    FROM
    (
        SELECT id FROM blogposts
        WHERE date_published <= NOW()
        AND deleted = 0 AND visible = 1
        AND title LIKE '%{de}%'
        ORDER BY date_created DESC
        LIMIT 0,50
    ) A
    INNER JOIN blogposts B USING (id)
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id

Nun ohne den genannten Index:

Altes Ergebnis erklären:

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE articles ALL blogpost_id NULL NULL NULL 6915 Using temporary; Using filesort
1 SIMPLE blogposts eq_ref PRIMARY PRIMARY 4 articles.blogpost_id 1 Using where

Neues Erklärungsergebnis:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     <derived2>  ALL     NULL    NULL    NULL    NULL    50   
1   PRIMARY     articles    ref     blogposts_id    blogposts_id    4   blogposts.id    1    
2   DERIVED     <derived3>  ALL     NULL    NULL    NULL    NULL    50   
2   DERIVED     B   eq_ref  PRIMARY     PRIMARY     4   A.id    1    
3   DERIVED     blogposts   ALL     deleted,visible,date_published  deleted     1       28198   Using filesort

Erläutern Sie das Ergebnis mit Index bei der alten Abfrage:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  blogposts   ref     PRIMARY,deleted,visible,date_published,deleted_vis...   deleted_visible_date_created    2   const,const     27771   Using where
1   SIMPLE  articles    ref     blogposts_id    blogposts_id    4   db.blogposts.id     1

Erläutern Sie das Ergebnis mit Index auf neuer Abfrage:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     <derived2>  ALL     NULL    NULL    NULL    NULL    50   
1   PRIMARY     articles    ref     blogposts_id    blogposts_id    4   blogposts.id    1    
2   DERIVED     <derived3>  ALL     NULL    NULL    NULL    NULL    50   
2   DERIVED     B   eq_ref  PRIMARY     PRIMARY     4   A.id    1    
3   DERIVED     blogposts   ref     deleted,visible,date_published,deleted_visible_dat...   deleted_visible_date_created    2       27771   Using where

Geschwindigkeit der alten Abfrage ohne/mit Index: 0.1835/0.0037

Geschwindigkeit auf einer neuen Abfrage ohne/mit Index: 0.1883/0.0035

Aufgrund der gerechten marginalen Unterschiede zwischen der alten/neuen Abfrage bevorzuge ich es, die alte Abfrage jedoch noch mit dem Index zu verwenden. Aber ich werde das berücksichtigen, als ob eines Tages die alte Abfrage zu langsam ist :)

Was für mich interessant wäre, ist zu wissen, wie Sie die Idee haben, den Index so festzulegen? Ich denke, wie ich diese Frage veröffentlicht habe, habe ich auch mit Deleted_visible versucht, aber anstelle von DATE_Created habe ich DATE_PUBLEFLEDS (wie in der Klausel) verwendet ...

Vielen Dank :)

Update von Rolandomysqldba 2011-05-19 13:03

Was es mir verschenkte, war das Wo und Ordnung durch Klauseln.

In der WHERE -Klausel sind gelöscht (0) und sichtbar (1) statische Werte. In der Reihenfolge nach Klausel war das Datum wie ein bewegendes Ziel unter allen Zeilen mit deleted = 0 und sichtbar = 1. Also habe ich zuerst die statischen Variablen vor den Index gestellt und dann das bewegte Ziel im Index. Normalerweise ist dies Teil des zugrunde liegenden Prinzips von SQL -Aussagen. Sie benötigen Indizes, die Ihre Where, Gruppen- und Bestellklauseln unterstützen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top