2010-12-18 10 views
1

Ich suche ab und zu mit "Select * von Posts, wie"% http: //% 'order by id desc limit 10 "und Suche ein paar andere Stichworte. In letzter Zeit ist die Auswahl unglaublich langsam.Wirklich langsame Abfrage war früher sehr schnell. Erklären zeigt Zeilen = 1 auf lokalen Backup aber Zeilen = 2287359 auf Server

mysql> explain select * from posts where reply like "%http://%" order by id desc limit 1; 
+----+-------------+-----------+-------+---------------+---------+---------+------+---------+-------------+ 
| id | select_type | table  | type | possible_keys | key  | key_len | ref | rows | Extra  | 
+----+-------------+-----------+-------+---------------+---------+---------+------+---------+-------------+ 
| 1 | SIMPLE  | posts  | index | NULL   | PRIMARY | 4  | NULL | 2287347 | Using where | 
+----+-------------+-----------+-------+---------------+---------+---------+------+---------+-------------+ 
1 row in set (0.00 sec) 

auf meinem Netbook mit 1 gig RAM Der einzige Unterschied ist es, die „ROWS“ -Spalte als 1. Es gibt nur 1,3 mil Beiträge in meinem Netbook zeigt. Der Server hat 6 GB RAM und einen schnellen Prozessor. Was sollte ich optimieren, damit es nicht furchtbar langsam ist? Kürzlich habe ich einen Index zur Suche nach userId hinzugefügt, von dem ich nicht sicher bin, ob er eine gute Wahl war, aber ich habe ihn dem Backup- und Produktionsserver hinzugefügt, kurz bevor dieses Problem auftrat. Ich könnte mir vorstellen, dass es damit zusammenhängt, dass es aufgrund eines verpassten Tweaks nicht möglich ist, in Ram zu sortieren?

Es scheint auch langsam zu sein, wenn ich Sachen wie "lösche von den Pfosten, wo threadId = X" tun, weiß nicht, wenn verwandt.

+1

Können Sie die CREATE-Anweisung für Ihre Tabelle (einschließlich Indizes) anzeigen? – enobrev

Antwort

2

Hinsichtlich

zu

SELECT * FROM posts WHERE reply LIKE "%http://%" ORDER BY id DESC LIMIT 1

Aufgrund der Wildcards auf beiden Seiten des http:// wird MySQL keinen Index auf reply verwenden, um schnell zu finden, was Sie suchen. Außerdem, weil Sie nach dem mit dem größten id fragen, muss MySQL alle Ergebnisse ziehen, um sicherzustellen, dass Sie den mit der größten 'id' haben.

Je nachdem, wie viel von den Daten des posts Tisches der reply gemacht wird, könnte es sinnvoll sein, eine Verbindung Index auf (id, reply), hinzuzufügen und die Abfrage etwas zu ändern wie

SELECT id FROM posts WHERE reply LIKE "%http://%" ORDER BY id DESC LIMIT 1

(die nur eine Indexausführung haben), dann an die Posts-Tabelle anfügen oder die Posts mit dem retrieved id s recen. Wenn die Abfrage index only execution hat und der Index in den Speicher und passt, ist er bereits im Speicher (aufgrund der normalen Verwendung oder der Absicht, ihn aufzuwärmen), Sie könnten die Abfrageausführung möglicherweise beschleunigen.

Nach alledem, wenn identische Abfragen auf zwei identischen Servern mit identischen Daten unterschiedliche Ausführungspläne und Ausführungszeiten geben, ist es möglicherweise Zeit OPTIMIZE TABLE posts die Indexstatistik zu aktualisieren und/oder die Tabelle zu defragmentieren. Wenn Sie kürzlich Indizes hinzugefügt/entfernt haben, könnten die Dinge in die Irre gegangen sein. Wenn die Daten fragmentiert sind, wenn sie Zeilen in PRIMARY KEY-Reihenfolge zieht, könnte sie außerdem über die gesamte Platte springen, um die Daten abzurufen.

In Bezug auf DELETE FROM posts WHERE threadId=X sollte es in Ordnung sein, solange es einen Index auf threadId gibt.

1

Welche Art von Indizes haben Sie auf Ihren Tischen? Eine gute Faustregel ist ein Index für die Spalten, die am häufigsten in Ihrer WHERE-Klausel vorkommen. Wenn Sie in Ihrer threadId-Spalte keinen Index haben, ist Ihre letzte Abfrage viel langsamer als bei Ihnen.

Ihre erste Abfrage (wählen Sie * aus Posts, wo Post wie '% http: //% langsam sein wird, einfach aufgrund der "Gefällt mir" in der Abfrage. Ich würde vorschlagen, Ihre Abfrage mit einer anderen WHERE-Klausel zu filtern - vielleicht nach Datum (die hoffentlich indiziert ist).

select * from posts where postdate > 'SOMEDATE' and post like '%http://%' 
+0

warum 'überall' LIKE ist schlecht: http://use-the-index-luke.com/sql/where-clause/searching-for-ranges/like-performance-tuning –

+0

Ich meine, in der Erklaerung die Zeilen abfragen zeigt 2287347, während in der Erläuterung für die Sicherung Zeilen = 1 angezeigt wird. In beiden verwende ich "Limit 1", aber aus irgendeinem Grund auf dem Server wird alles geladen oder alles durchsucht. Die Abfrage war früher schnell. Order by ID desc glaube ich ist schneller, weil es normalerweise nicht sortieren muss, wenn es ein Primärschlüssel ist (ich glaube, nicht sicher!). – ForeverConfused

+1

können Sie versuchen, FORCE INDEX? http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/; http://dev.mysql.com/doc/refman/5.1/en/index-hints.html – Tim

2

Indizes werden nicht dazu benutzt werden, wenn Sie Ihre Suche Vergleich mit einem „%“ beginnen Sie Problem mit

where reply like "%http://%" 

Wie bestätigt durch Ihre erklären, Es werden keine Indizes verwendet Die Geschwindigkeitsdifferenz kann durch Zwischenspeicherung verursacht werden

1

Können Sie einen After-Insert-Trigger schreiben, der den Text nach Teilzeichenfolge "http: //" untersucht und entweder den aktuellen Datensatz markiert oder seine ID in eine SPAM-Tabelle schreibt? Wie @ Brent sagte, werden Indizes nicht für Suchvorgänge mit Teilstrings verwendet.