2009-09-18 11 views
15

Ich habe eine bescheidene Tabelle, 277k Datensätze im Moment, die ich versuche, eine FULLTEXT Suche zu machen. Die Suche scheint sehr schnell zu sein, bis es in die Daten senden Phase kommt.MySQL "Daten senden" schrecklich langsam

Die Tabelle:

CREATE TABLE `sqinquiries_inquiry` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `ts` datetime NOT NULL, 
    `names` longtext NOT NULL, 
    `emails` longtext NOT NULL, 
    PRIMARY KEY (`id`), 
    FULLTEXT KEY `sqinquiries_inquiry_search` (`names`,`emails`) 
) ENGINE=MyISAM AUTO_INCREMENT=305560 DEFAULT CHARSET=latin1 

Die Abfrage:

SELECT * FROM `sqinquiries_inquiry` WHERE (
    MATCH (`sqinquiries_inquiry`.`names`) AGAINST ('smith' IN BOOLEAN MODE) OR 
    MATCH (`sqinquiries_inquiry`.`emails`) AGAINST ('smith' IN BOOLEAN MODE) 
) ORDER BY `sqinquiries_inquiry`.`id` DESC LIMIT 100 

Das Profil: (I scheinbar nutzlose Informationen snipped out)

+-------------------------+----------+ 
| Status     | Duration | 
+-------------------------+----------+ 
| preparing    | 0.000014 | 
| FULLTEXT initialization | 0.000015 | 
| executing    | 0.000004 | 
| Sorting result   | 0.000008 | 
| Sending data   | 2.247934 | 
| end      | 0.000011 | 
| query end    | 0.000003 | 
+-------------------------+----------+ 

Die DESCRIBE sieht gut aus, ein einfaches Motto: der Beschreibung:

id: 1 
select_type: SIMPLE 
table: sqinquiries_inquiry 
type: index 
possible_keys: NULL 
key: PRIMARY 
key_len: 4 
ref: NULL 
rows: 100 
Extra: Using where 

Also, was ich nicht verstehe, ist, wo die 2,25 Sekunden von Daten gesendet herkommt? Ich sehe ähnliche Leistung in Python und in der Konsole mysql App, beide verbinden zu localhost.

Updates:

  • pro Kommentar die durchschnittliche Zeilengröße anfordert, ist es: 53,8485
  • Per Kommentar, hier ist die DESCRIBE oben.
+0

Wie groß ist die Datenmenge, die Sie abrufen? Wenn Sie das nicht wissen, sehen Sie sich die Tabellenstatistik an und teilen Sie uns die durchschnittliche Zeilengröße mit. – longneck

+0

Ich war mir nicht sicher, wie ich die durchschnittliche Zeilengröße herausfinden sollte, also warf ich die Ausgabe auf: AVG (LÄNGE (Namen) + Länge (E-Mails) + Länge (ID) + Länge (ts)) als avg_length auswählen von sqinquiries_inquiry'. Wenn es einen besseren Weg gibt, lass es mich wissen. –

+0

Das Problem ist, dass Ihre 'FULLTEXT KEY' nicht verwendet wird. Könnten Sie bitte die 'DESCRIBE' veröffentlichen? – Quassnoi

Antwort

32

Die DESCRIBE sieht gut aus, ein einfacher Einzeiler.

Da Sie in Ihrer Abfrage nur eine Tabelle verwenden, kann es sich um nichts anderes als einen Einzeiler handeln.

Ihre Abfrage verwendet jedoch nicht den Index FULLTEXT.

Für den Index verwendbar zu sein, sollten Sie die Abfrage ein wenig umschreiben:

SELECT * 
FROM sqinquiries_inquiry 
WHERE MATCH (names, emails) AGAINST ('smith' IN BOOLEAN MODE) 
ORDER BY 
     id DESC 
LIMIT 100 

MATCH verwendet nur den Index, wenn die Sie gegen den genauen Satz von Spalten entsprechen der Index auf definiert ist.

So verwendet Ihre Abfrage den Index Scan auf id: Using index; Using where am Ende Ihrer DESCRIBE.

Sending data ist ziemlich irreführend: das ist tatsächlich Zeit, die zwischen dem Ende der vorherigen Operation und dem Ende der aktuellen Operation verstrichen ist.

So lief ich gerade diese Abfrage:

SET profiling = 1; 

SELECT * 
FROM t_source 
WHERE id + 1 = 999999; 

SHOW PROFILE FOR QUERY 39; 

, die eine einzelne Zeile und dieses Profil zurückgegeben:

'starting', 0.000106 
'Opening tables', 0.000017 
'System lock', 0.000005 
'Table lock', 0.000014 
'init', 0.000033 
'optimizing', 0.000009 
'statistics', 0.000013 
'preparing', 0.000010 
'executing', 0.000003 
'Sending data', 0.126565 
'end', 0.000007 
'query end', 0.000004 
'freeing items', 0.000053 
'logging slow query', 0.000002 
'cleaning up', 0.000005 

Da der Index nicht verwendbar ist, MySQL die vollständige Tabelle ausführen muss Scan.

0.126565 Sekunden sind die Zeit vom Beginn der Ausführung (die Zeit, in der die erste Zeile gelesen wurde) und das Ende der Ausführung (der Zeitpunkt, zu dem die letzte Zeile an den Client gesendet wurde).

Diese letzte Zeile befindet sich ganz am Ende des Tisches und es hat lange gedauert, sie zu finden und zu senden.

P. S. Edited die downvote zu entfernen :)

+0

Ich benutze Version 5.1.35. Und warum sollte der Index nicht nutzbar sein? –

+0

'@Jack M': Mein Beitrag erklärt warum. – Quassnoi

+0

'@Jack M.': und könnten Sie bitte Ihren Downvote erklären? – Quassnoi

-8

Ich glaube, Sie viele Daten übertragen, um einen eine langsame Netzwerkverbindung.

Anstatt * auszuwählen, wählen Sie nur die Spalten aus, die Sie wirklich benötigen.

Wenn Ihre Tabelle große Textfelder enthält, die Sie im Ergebnis anzeigen möchten, können Sie die Teilzeichenfolge verwenden, um nur die ersten Zeichen/Wörter des Textes zu übertragen.

Einige Clients unterstützen die Komprimierung der Ergebnispakete. Vielleicht möchten Sie sich das ansehen.

+2

Dies wird von localhost ausgeführt und gibt nur 100 Ergebnisse zurück. Die meisten Ergebnisse sind 1 E-Mail-Adresse und ein Name. Keine großen Datenmengen, keine langsamen Verbindungen. –