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 大小减半。
我有 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 大小减半。