Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL] 6 mln rekordów, indeks i SELECT wykonujący się grubo ponad minutę.
Forum PHP.pl > Forum > Bazy danych
adbacz
W tabeli mam ponad 6 mln rekordów, założony indeks na kolumnę 'created_at_timestamp' i wykonuję zapytanie po rekordy:
  1. (SELECT id FROM link WHERE ( created_at_timestamp <= 1485024231 AND created_at_timestamp >= 1484160231 ) ORDER BY id LIMIT 0, 1) UNION (SELECT id FROM link WHERE ( created_at_timestamp <= 1485024231 AND created_at_timestamp >= 1484160231 ) ORDER BY id LIMIT 99, 1)

To zapytanie wykonuje się naprawdę baaardzo długo: https://prnt.sc/g6g3ac

Sprawdziłem profilerem w PMA i pokazuje, że najdłużej działa Sending Data: https://prnt.sc/g6ggo2

Co może być tego przyczyną? Miał ktoś podobny problem?
bostaf
Z manuala:

Cytat
Sending data
The thread is reading and processing rows for a SELECT statement, and sending data to the client. Because operations occurring during this state tend to perform large amounts of disk access (reads), it is often the longest-running state over the lifetime of a given query.


Czyli mimo że z nazwy ten wątek wygląda na czyste przesyłanie danych, to z opisu wynika, że w grę wchodzi też czytanie i przetwarzanie całego setu. Na localu sam czas przesłania miałby marginalną wartość, co możnaby sprawdzić na przykład w MySQL Workbenchu czytając wartość "Fetch".

A daj jeszcze przed całym zapytaniem EXPLAIN i pokaż wynik. Może da się jakoś zoptymalizować całe zapytanie.
adbacz
Dziękuję za zainteresowanie tematem. Screen z rezultatu zapytania EXPLAIN:

http://prntscr.com/g7a9vs
Pyton_000
Wszystko jest ok. Po prostu zanim mysql wymieli Ci wynik i zwróci mija trochę czasu. A widać że zwraca Ci ~350k rekordów więc zanim poskacze po dysku i to odczyta ...

adbacz
Padły nam dyski SSD i robiliśmy migrację, myślałem, że to od tego ale jednak nie. Nadal tak długo to działa. Muszę po prostu inaczej podejść do problemu. Dziękuję za odpowiedzi.
Crozin
Mógłbyś zastanowić się nad utworzeniem indeksu, który będzie zawierać zarówno kolumnę created_at jak i id. Wtedy baza danych w ogóle nie będzie musiała dotykać dysku bo wszystkie dane odczyta bezpośrednio z indeksu: https://dev.mysql.com/doc/refman/5.7/en/glo..._covering_index
adbacz
Mam utworzone indeksy na te dwie kolumny: https://ibb.co/gab9rk

PS. Da się jakoś wymusić na bazie, by trzymała pewne dane w RAMie? Na przykład indeksy? Na serwerze mamy 64GB RAMu, może to by przyspieszyło operacje.
Crozin
1. Tabele typu MEMORY są trzymane właśnie w pamięci.
2. Indeksy są trzymane w pamięci.
3. Masz utworzone dwa indeksy na dwie kolumny, a potrzbowałbyś jednego na dwie kolumny by skorzystać z tego mechanizmu.
sazian
Patrząc na ilość tych indeksów nasuwa się mi się jedno pytanie: czy ta tabela ma aż tyle kolumn czy może utworzyłeś indeksy na wszystkich kolumnach ?
trueblue
Sprawdź co będzie po zmianie na UNION ALL.
Pilsener
1. Kolejność w WHERE ustaw tak, aby na początku był warunek wykluczający najwięcej rekordów.
2. Dość kosztowne jest sortowanie dużych tabel.
3. Sprawdzałbym po kolei od najprostszego zapytania typu "select id from link limit 0, 1", by znaleźć przyczynę
4. Nie wszystko da się zoptymalizować, pewnych rzeczy się nie przeskoczy
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.