MySQL bardzo wolno na bardzo proste zapytania SELECT

10

Mamy prostą aplikację internetową działającą na maszynie wirtualnej, która zapisuje swoje dane w bazie danych MySQL 5.5 za pomocą silnika InnoDB. Wszystko działało dobrze przez około trzy lata, ale nagle stało się bardzo wolne.

Na przykład mam bardzo prosty adres przechowujący tabelę:

CREATE TABLE `addresses` (
  `address_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) CHARACTER SET latin1 NOT NULL,
  `firstname` varchar(64) CHARACTER SET latin1 NOT NULL,
  `street` varchar(64) CHARACTER SET latin1 NOT NULL,
  `housenumber` varchar(16) CHARACTER SET latin1 NOT NULL,
  `zip` varchar(5) CHARACTER SET latin1 NOT NULL,
  `city` varchar(64) CHARACTER SET latin1 NOT NULL,
  `email` varchar(64) CHARACTER SET latin1 NOT NULL,
  `phone` varchar(16) CHARACTER SET latin1 NOT NULL,
  `birthdate` date NOT NULL,
  PRIMARY KEY (`address_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

Ta tabela zawiera około 800 wpisów, co naprawdę nie jest wiele. Ale uruchomienie zapytania

SELECT * FROM addresses

do celów testowych wydaje się, że nigdy się nie kończy. Sprawdziłem to za pomocą interfejsu mysql CLI na samym serwerze: wypisuje kilka wierszy tabeli, a następnie czeka bardzo długo, aż wypisze kolejne wiersze.

Być może jest to problem w fazie przesyłania danych, ale nie jestem pewien.

Maszyna wirtualna ma 2 GB pamięci RAM i wykorzystuje tylko 320 MB. Procesor działa również na bardzo niskim poziomie 1–2%. mytop nie wyświetla żadnych innych zapytań blokujących serwer. Administrator IT powiedział, że nic nie zmienili po stronie sprzętowej.

Próbowałem już czegoś takiego jak zrestartowanie serwera bazy danych, zrestartowanie maszyny wirtualnej. Nic nie pomogło.

edytować:

EXPLAIN SELECT * FROM addresses

daje mi ten wynik:

+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | addresses | ALL  | NULL          | NULL | NULL    | NULL |  793 |       |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
tabb
źródło
Virtual Box, Xen czy coś jeszcze? Jak skonfigurowany jest dysk hosta? czy są też inne maszyny wirtualne na tym samym komputerze, które działają wolno? Odpowiedzi na te pytania mogą ujawnić odpowiedź
Matt
Nie jestem właścicielem hiperwizora, więc tak naprawdę nie mogę na to odpowiedzieć. Zapytałem już administratora hiperwizora, czy wie o jakichkolwiek ostatnich zmianach, ale odpowiedział „nie”.
tabb
jeśli możesz, zamknij mysql i uruchom test dysku i pamięci. To nie musi być skomplikowane. Chodzi o to, aby wyizolować, czy jest to problem z mysql, być może problem z indeksem, jak wskazano w odpowiedzi poniżej, lub bardziej powszechny.
Matt
Dobra uwaga, doświadczyłem, że prawdopodobnie nie jest to problem z mysql. Uruchamianie mysql -u username -ppassword mydb -e 'SELECT * FROM addressesdziała powoli, ale dołączając `> test.txt`, działa bardzo szybko. To prawdopodobnie byłoby inne pytanie !? Jak mogę to zbadać?
tabb
Skontaktuj się z właścicielem hiperwizora i poproś go o sprawdzenie dzienników pod kątem błędów. W szczególności błędy dysku. Powiedz mu swoje objawy. Utwórz kopię zapasową teraz.
Matt

Odpowiedzi:

13

Jeśli obciążenie procesora jest niskie, oznacza to, że nie ma problemów z brakującymi indeksami, w takim przypadku zapytanie wymagałoby tylko więcej procesora i dostępu do dysku. Powiedziałeś też, że działało dobrze przez 3 lata.

Czy sprawdziłeś ogólną szybkość dostępu do dysku (szczególnie na partycji, na której znajduje się baza danych)? Np. Używając dd jak tutaj . To, co opisujesz, brzmi jak martwy dysk lub na wpół martwy nalot. Mam nadzieję, że masz kopie zapasowe?

użytkownik3648611
źródło
Trafne spostrzeżenie. Może to być coś tak prostego jak błąd dysku na hoście.
Matt
9

Możesz spróbować kilku rzeczy,

  1. Czy masz skonfigurowane indeksy?

Indeksowanie umożliwia szybkie wyszukiwanie rekordów bez uprzedniego pełnego skanowania tabeli, co znacznie skraca czas wykonywania.

CREATE INDEX idx_name ON addresses(name);
  1. Przed uruchomieniem zapytania użyj najpierw słowa kluczowego EXPLAIN,

W przypadku użycia przed zapytaniem SELECT opisuje, w jaki sposób MySQL zamierza wykonać zapytanie oraz liczbę wierszy, które będzie musiał przetworzyć przed jego zakończeniem.

  1. Wprowadź zmiany w pliku mysql.ini, jeśli jest to maszyna wirtualna, zwiększy pamięć RAM i skonfiguruj plik mysql.ini, aby sprawdzić, czy wydajność wzrośnie.

Istnieje wiele optymalizatorów MySQL, które mogą cię poprowadzić.

Pomóż to pomaga

Anthony Fornito
źródło
Ok, ale tworzenie indeksu na dość małej tabeli (<800 wierszy) wydaje się nie być tak pomocne, jak bym potrzebował. Zakończenie cytowanego powyżej zapytania zajmuje ponad minutę. Pełny skan tak małego stołu nie powinien trwać tak długo.
tabb
Więc ... dodałeś indeksy? Jeśli nie jesteś pewien, na czym polega problem, zacznę podstawową i zejdę na dół. Dodanie indeksów zwiększy wydajność tylko wtedy, gdy zostanie wykonane poprawnie.
Anthony Fornito,
Tak, dodałem indeks do kolumny nazwy. Ale moje powyższe zapytanie nie ma nawet żadnej klauzuli ograniczającej WHERE, więc będzie musiał przeczytać całą tabelę i wydrukować ją. Dodano indeks nie pomógł.
tabb
Dodałem wynik zapytania EXPLAIN powyżej. Dla mnie to wygląda dobrze, ale wydajność jest nadal bardzo niska. Nie mogę zwiększyć pamięci RAM, ponieważ nie jestem administratorem menedżera wirtualizacji. Ale htoppokazuje, że zużywa się tylko 307 MB z 2050 MB pamięci RAM.
tabb
O indeksach naprawdę musisz pomyśleć o tym, które kolumny mają być indeksowane, nie chcesz po prostu indeksować wszystkiego, indeksować te, które mają największą liczbę, robię pewne dzikie założenia, ale zacznę od name„imienia”. Po drugie, czy jesteś pewien, że indeksowanie przebiegło poprawnie? możliwy_klucz: NULL, jeśli kolumna ma wartość NULL, oznacza to, że nie można znaleźć odpowiednich indeksów.
Anthony Fornito,