2009-08-19 12 views
3

Ich habe einen ziemlich einfachen Prozess ausgeführt, der RSS-Feeds periodisch aufnimmt und Artikel in einer MySQL-Datenbank aktualisiert.Einfache MySQL-Abfrage dauert 2 bis 3 Sekunden?

Die Artikeltabelle ist jetzt in etwa 130k Zeilen gefüllt. Für jeden gefundenen Artikel prüft der Prozessor, ob der Artikel bereits existiert. Diese Abfragen dauern fast immer 300 Millisekunden und etwa alle 10 oder 20 Versuche dauern mehr als 2 Sekunden.

SELECT id FROM `articles` WHERE (guid = 'http://example.com/feed.rss') LIMIT 1; 
# Query_time: 2.754567 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 0 

Ich habe einen Index für die Spalte guid aber wann immer ein neuer Artikel angetroffen wird, wird es auf die Artikel-Tabelle hinzugefügt - (? Rechts), um die Abfrage-Cache ungültig zu machen.

Einige der anderen Felder im Protokoll der langsamen Abfrage protokollieren mehr als 120 Zeilen.

Natürlich benötigen diese Abfragen auf meiner Entwicklungsmaschine etwa 0,2 Millisekunden.

Der Server ist ein virtueller Host von Engine Yard Solo (EC2) mit 1,7 GB Speicher und welcher CPU EC2 in diesen Tagen auch ausgeliefert wird.

Jeder Rat würde sehr geschätzt werden.

aktualisieren

Da es das Problem zwischen dem Stuhl war sich herausstellt und der Tastatur.

Ich hatte einen Index für 'ID', aber war auf 'GUID' Abfrage.

Das Hinzufügen eines Indexes zu 'guid' hat die Abfragezeit auf jeweils 0,2 ms verkürzt.

Danke für alle hilfreichen Tipps an alle!

+0

1,7 'MB' der Speicher, die ziemlich klein ist. Mein 286 Computer hatte 1 MB tho. – pjp

+0

Ja, bitte bearbeiten und korrigieren Sie diesen Betrag, weil ich sehe und Ding "keine Möglichkeit" –

+0

Fixed die Erinnerung Hinweis - es hätte GB sein sollen. Vielen Dank! –

Antwort

4

Run:

EXPLAIN SELECT id FROM `articles` WHERE (guid = 'http://example.com/feed.rss') LIMIT 1; 

Beachten Sie die EXPLAIN vor. Das wird Ihnen sagen, was MySQL tut. Es ist schwer zu glauben, dass man eine Zeile aus einem Index abtasten könnte, wenn man ernsthaft versucht, die Maschine zu überlasten und/oder zu verprügeln. Wenn ich die Zeilenanzahl von 0 betrachte, vermute ich, dass MySQL einen vollständigen Tabellenscan durchgeführt hat, um nichts zu finden, was wahrscheinlich bedeutet, dass Sie nicht den Index haben, von dem Sie denken, dass Sie ihn tun.

Ihre andere Frage zu beantworten, wenn Sie jede Änderung der articles Tabelle machen, werden alle Abfrage-Cache-Einträge, die Tabelle beinhalten, werden für ungültig erklärt.

1

Das Protokoll sagt, dass keine Zeilen gelesen oder sogar untersucht wurden, so ist das Problem nicht mit Ihrer Abfrage, sondern höchstwahrscheinlich mit Ihrem Server. Die Achillesferse von EC2 ist seine IO/s, vielleicht musste MySQL den Index von der Festplatte laden, aber die Festplatten des Servers waren vollständig gesättigt.

Wenn Ihr Index klein genug ist, in den Speicher passen (stellen Sie sicher, dass Ihre my.cnf genug Speicher key_buffer (MyISAM) oder innodb_buffer_pool_size (InnoDB) zuordnet), sollten Sie in der Lage sein, es Vorspannung mit

SELECT guid FROM articles 

Überprüfen Sie die EXPLAIN, um sicherzustellen, dass dort "Using Index" steht."Wenn dies nicht der Fall, dies sollte man:

SELECT guid FROM articles FORCE INDEX (guid) WHERE LENGTH(guid) > 0 

Alternativ, wenn guid nicht Primarykey oder UNIQUE ist, können Sie seinen Index entfernen und eine andere indexierte Spalte angelegt Datensätze abzurufen schnell zu einem Bruchteil . die Indexgröße die Spalte guid_crc32 wäre ein INT UNSIGNED sein und würde die CRC32 von guid

ALTER TABLE articles ADD COLUMN guid_crc32 INT UNSIGNED, ADD INDEX guid_crc32 (guid_crc32); 
UPDATE articles SET guid_crc32 = CRC32(guid); 

Ihre SELECT-Abfrage dann wie folgt aussehen würde halten:

SELECT id FROM articles WHERE guid = 'http://example.com/feed.rss' AND guid_crc32 = CRC32('http://example.com/feed.rss') LIMIT 1; 

Der Optimierer sollte den Index guid_crc32 verwenden, der sowohl schneller als auch kleiner als das Durchsuchen guid sein sollte.

+0

Ich habe gerade den Teil bemerkt, wo Luke sagt, dass dieselbe Abfrage, die immer wieder ausgeführt wird, alle paar Dutzend Versuche langsam sein würde, was meine Theorie über das Laden des Index von der Platte schwächt. Es sei denn, der Server hat so wenig Speicher für den Index reserviert, dass er alle paar Dutzend Versuche austauscht. –

0

Wenn diese Tabelle sehr oft aktualisiert wird, aktualisiert mysql die Indexwerte möglicherweise nicht richtig. Probieren Sie "CHECK TABLE-Artikel" aus, um die Indexzahlen zu aktualisieren und festzustellen, ob Ihre Tabelle in Ordnung ist.

versuchen Sie auch zu sehen, wenn EXPLAIN auf Ihre Abfrage die gleichen Ergebnisse auf Ihrem dev und prod Maschinen geben. Wenn die Ergebnisse unterschiedlich sind, versuchen Sie OPTIMIZE TABLE.

Sind diese myisam oder innodb Tabellen?

0

Angenommen, GUID ist indiziert und ID ist Ihr Primärschlüssel, etwas ist "falsch". In diesem Szenario handelt es sich um eine Nur-Index-Abfrage. Der Index wird aus dem Speicher gestoßen und die Festplatten sind vielleicht beschäftigt.

Abhängig von Ihrem Update/Einfügen/Löschen Muster, weinen Sie Datenbank für einen "optimieren" Befehl.

SQL-Befehle Ich möchte die Ausgabe sehen:

show table status like 'articles'; 
explain SELECT id FROM `articles` WHERE (guid = 'http://example.com/feed.rss') LIMIT 1; 
explain articles; 

Systembefehle Ich mag würde die Ausgabe von (unter der Annahme, Linux), um zu sehen:

iostat 5 5 

Sagen Sie uns, wie viel Erinnerung, die Sie haben, weil 1.7mb falsch ist, oder etwas wirklich aufregendes geschieht.

Bearbeiten Wie viel Speicher ist für Ihren SQL Server in my.cnf verfügbar?

Verwandte Themen