Mysql JOIN 查询显然很慢

Mysql JOIN query apparently slow

我有 2 个 table。第一个称为 stazioni,我在其中存储来自某个气象站的实时天气数据,第二个称为 archivio2,其中存储存档的日期数据。这两个 table 有共同的 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`);

在地图上,我通过日历调用日期来搜索 archive2 table 上的数据,通过这个 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.5s/1.0s)。 我尝试在 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 

UPDATE:如果我从 'IDStazione' 中删除索引,查询就会正常进行。但是这样我就失去了其他查询的所有优势和速度......为什么如果我在那个字段上放置索引,只有那个查询变慢?

在你的 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 结果。我希望 table 顺序被交换并且 key 列将显示 Data2(对于 c)和 ID(对于 o ).

(修复 DATE 是主要的性能解决方案;这里是一个不太重要的问题。)

table 比需要的大得多。大小会影响磁盘 space,并在某种程度上影响速度。

您有 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 个字节。

table 中的“localita varchar(100)”在做什么?好像你可以在需要的时候JOIN到车站table?删除它可能会将 table 大小减半。