2009-09-18 29 views
15

Mam tabelę o niewielkich rozmiarach, obecnie 277k rekordów, które próbuję wykonać przy wyszukiwaniu FULLTEXT. Wyszukiwanie wydaje się bardzo szybkie, dopóki nie przejdzie do fazy wysyłania danych.MySQL "Wysyłanie danych" strasznie powolne

Tabela:

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 

Query:

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 

Profile: (I wycięte z pozoru bezużyteczne informacje)

+-------------------------+----------+ 
| 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 | 
+-------------------------+----------+ 

DESCRIBE wygląda świetnie, prosta wykładziny: The opisać:

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 

Więc co ja nie rozumiem, gdzie jest 2,25 sekundy Wysyłanie danych pochodzących z? Widzę podobną wydajność w Pythonie i aplikacji konsoli mysql, obie łączą się z localhost.

Aktualizacje:

  • Per komentarzu wnioskiem o średniej wielkości rzędu, to jest: 53,8485
  • na komentarz, tutaj jest powyżej DESCRIBE.
+0

Jak duża jest ilość pobieranych danych? jeśli nie wiesz, spójrz na statystyki tabeli i powiedz nam średni rozmiar wiersza. – longneck

+0

Nie byłem pewien, jak obliczyć średni rozmiar wiersza, więc wyrzuciłem tam jego wynik: SELECT AVG (DŁUGOŚĆ (nazwy) + DŁUGOŚĆ (e-maile) + DŁUGOŚĆ (id) + DŁUGOŚĆ (ts)) jako avg_length od sqinquiries_inquiry'. Jeśli jest lepszy sposób, daj mi znać. –

+0

Problem polega na tym, że twój klucz "FULLTEXT KEY" nie jest używany. Czy mógłbyś opublikować "DESCRIBE"? – Quassnoi

Odpowiedz

32

DESCRIBE wygląda świetnie, prosta liner.

Ponieważ w zapytaniu używana jest tylko jedna tabela, nie może to być nic innego niż jednolinijkowa.

Jednak zapytanie nie korzysta z indeksu FULLTEXT.

dla indeksu nadawać się do użytku, należy przepisać kwerendy trochę:

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

MATCH tylko korzysta z indeksu, jeśli dopasujesz przed dokładnym zestaw kolumn indeks jest zdefiniowany.

Twoje zapytanie wykorzystuje skanowanie indeksu na id: Using index; Using where na samym końcu Twojej DESCRIBE.

Sending data jest dość myląca: faktycznie upłynął czas między końcem poprzedniej operacji a końcem bieżącej operacji.

Na przykład, po prostu zabrakło tej kwerendy:

SET profiling = 1; 

SELECT * 
FROM t_source 
WHERE id + 1 = 999999; 

SHOW PROFILE FOR QUERY 39; 

który zwrócony jednym rzędzie oraz profilu:

'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 

Ponieważ indeks nie jest użyteczny, MySQL musi przeprowadzić pełną tabelę skandować.

0.126565 sekund to czas od początku wykonania (czas odczytu pierwszego wiersza) i koniec wykonania (czas ostatniego wysłania wiersza do klienta).

Ten ostatni wiersz znajduje się na samym końcu tabeli i znalezienie go zajęło dużo czasu.

P. S. Edited usunąć downvote :)

+0

Używam wersji 5.1.35. I dlaczego indeks nie byłby użyteczny? –

+0

'@Jack M.': mój post wyjaśnia dlaczego. – Quassnoi

+0

'@Jack M.': czy mógłbyś wyjaśnić swoje zdanie? – Quassnoi

-8

myślę przesyłanie dużej ilości danych z wyborem wolnego połączenia sieciowego.

Zamiast wybierać * należy wybrać tylko te kolumny, które naprawdę są potrzebne.

Jeśli Twoja tabela zawiera duże pola tekstowe, które chcesz pokazać w wynikach, możesz użyć podłańcucha do przeniesienia tylko pierwszych kilku znaków/słów w tekście.

Niektórzy klienci obsługują kompresję pakietów wynikowych. Może chcesz na to spojrzeć.

+2

Działający z localhost, zwracający tylko 100 wyników, a najwięcej wyników to 1 adres e-mail i jedna nazwa. Niezbyt duże ilości danych, a nie wolne połączenia. –

Powiązane problemy