Mysql JOIN запрос явно медленный - PullRequest
1 голос
/ 18 мая 2019

У меня есть 2 таблицы. Первый называется stazioni , где я храню данные о погоде в реальном времени с какой-либо метеостанции, а второй - archivio2 , где хранятся архивные данные о днях. Обе таблицы имеют общие данные ID станции (ID для Stazioni, IDStazione для Archvio2).

stazioni (1743 строки)

CREATE TABLE `stazioni` (
  `ID` int(10) NOT NULL,
  `user` varchar(100) NOT NULL,
  `nome` varchar(100) NOT NULL,
  `email` varchar(50) NOT NULL,
  `localita` varchar(100) NOT NULL,
  `provincia` varchar(50) NOT NULL,
  `regione` varchar(50) NOT NULL,
  `altitudine` int(10) NOT NULL,
  `stazione` varchar(100) NOT NULL,
  `schermo` varchar(50) NOT NULL,
  `installazione` varchar(50) NOT NULL,
  `ubicazione` varchar(50) NOT NULL,
  `immagine` varchar(100) NOT NULL,
  `lat` double NOT NULL,
  `longi` double NOT NULL,
  `file` varchar(255) NOT NULL,
  `url` varchar(255) NOT NULL,
  `temperatura` decimal(10,1) DEFAULT NULL,
  `umidita` decimal(10,1) DEFAULT NULL,
  `pressione` decimal(10,1) DEFAULT NULL,
  `vento` decimal(10,1) DEFAULT NULL,
  `vento_direzione` decimal(10,1) DEFAULT NULL,
  `raffica` decimal(10,1) DEFAULT NULL,
  `pioggia` decimal(10,1) DEFAULT NULL,
  `rate` decimal(10,1) DEFAULT NULL,
  `minima` decimal(10,1) DEFAULT NULL,
  `massima` decimal(10,1) DEFAULT NULL,
  `orario` varchar(16) DEFAULT NULL,
  `online` int(1) NOT NULL DEFAULT '0',
  `tipo` int(1) NOT NULL DEFAULT '0',
  `webcam` varchar(255) DEFAULT NULL,
  `webcam2` varchar(255) DEFAULT NULL,
  `condizioni` varchar(255) DEFAULT NULL,
  `Data2` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

archivio2 (2 127 347 строк)

CREATE TABLE `archivio2` (
  `ID` int(10) NOT NULL,
  `IDStazione` int(4) NOT NULL DEFAULT '0',
  `localita` varchar(100) NOT NULL,
  `temp_media` decimal(10,1) DEFAULT NULL,
  `temp_minima` decimal(10,1) DEFAULT NULL,
  `temp_massima` decimal(10,1) DEFAULT NULL,
  `pioggia` decimal(10,1) DEFAULT NULL,
  `pressione` decimal(10,1) DEFAULT NULL,
  `vento` decimal(10,1) DEFAULT NULL,
  `raffica` decimal(10,1) DEFAULT NULL,
  `records` int(10) DEFAULT NULL,
  `Data2` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Индексы, которые я установил

-- Indexes for table `archivio2`
--
ALTER TABLE `archivio2`
  ADD PRIMARY KEY (`ID`),
  ADD KEY `IDStazione` (`IDStazione`),
  ADD KEY `Data2` (`Data2`);

-- Indexes for table `stazioni`
--
ALTER TABLE `stazioni`
  ADD PRIMARY KEY (`ID`),
  ADD KEY `Tipo` (`Tipo`);
ALTER TABLE `stazioni` ADD FULLTEXT KEY `localita` (`localita`);

На карте я вызываю по календарю дату для поиска данных в таблице archive2, по этому запросу INNER JOIN (я поставил пример даты):

SELECT *, c.pioggia AS rain, c.raffica AS raff, c.vento AS wind, c.pressione AS press
FROM stazioni as o
INNER JOIN archivio2 as c ON o.ID = c.IDStazione
WHERE c.Data2 LIKE '2019-01-01%'

Все работает нормально, но время, необходимое для показа результата, очень медленное (4/5 секунд), даже если время выполнения запроса кажется нормальным (около 0,5 с / 1,0 с). Я попытался выполнить запрос на PHPMyadmin, и результаты совпадают. Время выполнения быстро, но время показывать результат крайне медленно.

ОБЪЯСНИТЬ результат запроса

id  select_type table   type    possible_keys       key         key_len ref                 rows    Extra
1   SIMPLE      o       ALL     PRIMARY,ID          NULL        NULL    NULL                1743    NULL    
1   SIMPLE      c       ref     IDStazione,Data2    IDStazione  4       sccavzuq_rete.o.ID  1141    Using where 

URL для проверки: https://retemeteo.lineameteo.it/index_archivio.php


ОБНОВЛЕНИЕ : запрос выполняется нормально, если я удаляю индекс из 'IDStazione'. Но таким образом я потерял все преимущества и скорость в других запросах ... почему только этот запрос становится медленным, если я помещаю индекс в это поле?

Ответы [ 2 ]

3 голосов
/ 18 мая 2019

В вашем предложении WHERE

WHERE c.Data2 LIKE '2019-01-01%'

значение Data2 должно быть приведено к строке. Для этого условия нельзя использовать индекс.

Измените его на

WHERE c.Data2 >= '2019-01-01' AND c.Data2 < '2019-01-01' + INTERVAL 1 DAY

Таким образом, двигатель должен иметь возможность использовать индекс на (Data2).

Теперь проверьте результат EXPLAIN. Я ожидаю, что порядок таблиц поменяется местами, и в столбце key отобразятся Data2 (для c) и ID (для o).

1 голос
/ 19 мая 2019

(Исправление ДАТЫ является основным решением для повышения производительности; здесь проблема менее критична.)

Таблицы намного больше, чем необходимо.Размер влияет на дисковое пространство и, в некоторой степени, на скорость.

У вас есть 1743 станции, но тип данных - это 32-разрядное (4-байтовое) число (INT).SMALLINT UNSIGNED позволит использовать 64K радиостанций и использовать только 2 байта.

Становится ли там очень, очень жарко?Как 999999999,9 градусов?DECIMAL(10.1) занимает 5 байтов;DECIMAL(4,1) занимает всего 3 и позволяет до 999,9 градуса.DECIMAL(3,1) имеет максимум 99,9 и занимает всего 2 байта.

Что делает "localita varchar (100)" в большой таблице?Похоже, вы могли бы JOIN к таблице станций, когда вам это нужно?Удаление этого может сократить размер таблицы в два раза.

...