MySQL的JOIN查询显然慢

时间:2019-05-18 09:37:12

标签: mysql database inner-join query-performance

我有2张桌子。第一个称为 stazioni ,用于存储某个气象站的实时天气数据,第二个称为 archivio2 ,用于存储存档的日数据。这两个表的ID站数据相同(stazioni上的ID,archvio2上的IDStazione)。

stazioni (1,743行)

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`);

在地图上,我通过日历调用日期,以通过这个INNER JOIN查询(在示例中输入日期)来搜索archive2表上的数据:

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%'

一切正常,但是即使查询执行时间似乎还可以(大约0.5s / 1.0s),显示结果所需的时间却确实很慢(4/5秒)。 我试图在PHPMyadmin上执行查询,结果是相同的。执行时间很快,但是显示结果的时间却非常缓慢。

EXPLAIN查询结果

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 

要测试的网址:https://retemeteo.lineameteo.it/index_archivio.php


更新:如果我从“ IDStazione”中删除索引,查询将正常进行。但是以这种方式,我失去了其他查询的所有优势和速度...如果我在该字段上添加索引,为什么只有该查询变慢?

2 个答案:

答案 0 :(得分:3)

在您的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 :(得分:1)

(解决DATE是主要的性能解决方案;这是一个不太关键的问题。)

表太大了。大小会影响磁盘空间,并在一定程度上影响速度。

您有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进入车站表?删除该表可能会使表的大小减半。