Mam tabeli MySQL z 100k wierszy, która rejestruje kilka logi serwera utworzony jako:Update-przyłączyć MySQL bardzo powolny w porównaniu do kwerendy wybierającej bez indeksów
CREATE TABLE `logs` (
`id` INT NOT NULL AUTO_INCREMENT,
`ip` VARCHAR(16) NULL,
`date` DATETIME NULL,
`session_time` SMALLINT UNSIGNED NULL,
PRIMARY KEY (`id`));
Próbuję obliczyć czas trwania sesji jako różnica czasu między kolejnymi rzędami tego samego adresu IP. Jestem w stanie osiągnąć z następującej kwerendy wybierającej, która zajmuje mniej niż sekundę:
SELECT * FROM logs AS a
LEFT JOIN (
SELECT id,
from_unixtime(@diff) AS starttime,
date AS endtime,
IF(@diff = 0, 0, (unix_timestamp(date) - @diff)/60) AS session_time1,
@diff := unix_timestamp(date)
FROM logs,
(SELECT @diff := 0) AS x
ORDER BY ip, logs.date
) AS b ON
a.id = b.id
Jednak, gdy staram się korzystać z poprzedniej kwerendy w aktualizacji dołącz do aktualizacji Czas sesji, następujące zapytanie aktualizacja trwa dłużej niż 600 sekund:
UPDATE logs AS a
LEFT JOIN (
SELECT id,
from_unixtime(@diff) AS starttime,
date AS endtime,
IF(@diff = 0, 0, (unix_timestamp(date) - @diff)/60) AS session_time1,
@diff := unix_timestamp(date)
FROM logs,
(SELECT @diff := 0) AS x
ORDER BY ip, logs.date
) AS b ON
a.id = b.id
SET session_time = session_time1;
Czego mi brakuje?
Dzięki!
UPDATE: Oto EXPLAIN
z select
:
+----+-------------+------------+--------+---------------+------+--------+
| id | select_type | table | type | possible_keys | key | rows |
+----+-------------+------------+--------+---------------+------+--------+
| 1 | PRIMARY | a | ALL | NULL | NULL | 109029 |
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | 108680 |
| 2 | DERIVED | <derived3> | system | NULL | NULL | 1 |
| 2 | DERIVED | logs | ALL | NULL | NULL | 109029 |
| 3 | DERIVED | NULL | NULL | NULL | NULL | NULL |
+----+-------------+------------+--------+---------------+------+--------+
'GDZIE ip =" ... "'? Wygląda na to, że aktualizujesz wszystkie wpisy 100k, ale te, które wybierasz ("LEFT JOIN" = elementy, które nie są zgodne z wybranymi regułami w pierwszej grupie). Spróbuj użyć 'INNER JOIN'? –
Dzięki Alejandro, ale nie do końca rozumiem twój komentarz. Dlaczego połączenie wewnętrzne byłoby lepsze? Co masz na myśli mówiąc o klauzuli "where"? – kahlo
Przepraszam, powinienem był to lepiej wyjaśnić. Kiedy używasz 'UPDATE', zwykle używasz klauzuli" WHERE "do filtrowania, które dane powinny być aktualizowane. W twoim przypadku, jeśli chcesz zaktualizować pod konkretny adres IP, "WHERE ip =" "powinno być lepiej przetwarzać tylko dane z tym konkretnym adresem IP (myślę, że twoje zapytanie przetwarza każdy rekord w twojej tabeli , nawet jeśli nie wszystkie z nich są aktualizowane). –