SQL无限加载
SQL Infinite loading
我有一个包含 100 万条记录的数据库,对于使用 JOIN、GROUP BY、ORDER 的简单查询,它的响应时间大约为 1.2 秒,它工作正常......没关系这没有问题。我正在努力使用 table 别名来简化查询,但是当我使用两个 table 别名或更多别名执行简单查询时,请求永远不会结束并且 MariaDB 不再响应,我必须重新启动手动服务。
怎么了?
结构如下:
CREATE TABLE `values` (
`id` mediumint(11) UNSIGNED NOT NULL,
`date` int(11) NOT NULL DEFAULT '0',
`indexVar` int(11) NOT NULL,
`value` float NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
数据:
exemple
工作查询:
SELECT
v.date,
v.value
FROM
`values` AS v
WHERE
v.date > 1548460800 AND v.indexVar = 6 OR v.indexVar = 2
expected result
无限加载查询:
SELECT DISTINCT
v.date,
v1.value,
v2.value
FROM
`values` AS v,
`values` AS v1,
`values` AS v2
WHERE
v.date > 1548460800 AND v1.indexVar = 6 AND v2.indexVar = 2
expected result
您没有在查询中包含任何连接条件。
如果值 table 有 100 万行,那么两次包含它会得到一个包含 100 万 * 100 万 = 1 万亿行的结果集。您正在应用一些条件,但您仍然会得到大量结果。 (并且您包含了值 table 三次!)
假设您有一个包含一百万行的 table,每行只是 1 到 1 百万之间的整数。如果您执行 select value from values where value > 900000
,那么您将获得 100,000 行。但是如果你说 select value from values v, values v2 where v.value > 900000
那么对于与 v.value > 900000
条件匹配的 100,000 行中的每一行,你将从 v2 中获得所有百万行。即使您将相同的过滤器应用于 v2(即 v2.value > 900000
),查询仍将为原始值中的每一行 return 100,000 v2 行 table--总共 100 亿行。
如果 date
是 table 的主键,那么您必须确保每个结果行中的所有 date
值都相同:
select v.date, v1.value, v2.value
from values v, values v1, values v2
where v.date = v1.date and v.date = v2.date
and v1.indexVar = 6 and v2.indexVar = 2
或更好:
select v.date, v1.value, v2.value
from values v
inner join values v1 on (v1.date = v.date)
inner join values v2 on (v2.date = v.date)
where v1.indexVar = 6 and v2.indexVar = 2
如果主键是id
,那么对id
做同样的事情。 (你说你想根据日期对齐行,所以不确定哪一列最重要。)
您可以尝试使用伪造的聚合函数和组来减少过滤条件下的结果
SELECT date
, max(case when v.indexVar = 6 then v.values end) v1_value
, max(case when v.indexVar = 2 then v.values end) v2_value
FROM values
WHERE
date > 1548460800 AND indexVar = 6 OR indexVar = 2
group by date
你还应该添加一个合适的复合索引
create index idx1 on values ( indexVar, date)
我有一个包含 100 万条记录的数据库,对于使用 JOIN、GROUP BY、ORDER 的简单查询,它的响应时间大约为 1.2 秒,它工作正常......没关系这没有问题。我正在努力使用 table 别名来简化查询,但是当我使用两个 table 别名或更多别名执行简单查询时,请求永远不会结束并且 MariaDB 不再响应,我必须重新启动手动服务。
怎么了?
结构如下:
CREATE TABLE `values` (
`id` mediumint(11) UNSIGNED NOT NULL,
`date` int(11) NOT NULL DEFAULT '0',
`indexVar` int(11) NOT NULL,
`value` float NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
数据: exemple
工作查询:
SELECT
v.date,
v.value
FROM
`values` AS v
WHERE
v.date > 1548460800 AND v.indexVar = 6 OR v.indexVar = 2
expected result
无限加载查询:
SELECT DISTINCT
v.date,
v1.value,
v2.value
FROM
`values` AS v,
`values` AS v1,
`values` AS v2
WHERE
v.date > 1548460800 AND v1.indexVar = 6 AND v2.indexVar = 2
expected result
您没有在查询中包含任何连接条件。
如果值 table 有 100 万行,那么两次包含它会得到一个包含 100 万 * 100 万 = 1 万亿行的结果集。您正在应用一些条件,但您仍然会得到大量结果。 (并且您包含了值 table 三次!)
假设您有一个包含一百万行的 table,每行只是 1 到 1 百万之间的整数。如果您执行 select value from values where value > 900000
,那么您将获得 100,000 行。但是如果你说 select value from values v, values v2 where v.value > 900000
那么对于与 v.value > 900000
条件匹配的 100,000 行中的每一行,你将从 v2 中获得所有百万行。即使您将相同的过滤器应用于 v2(即 v2.value > 900000
),查询仍将为原始值中的每一行 return 100,000 v2 行 table--总共 100 亿行。
如果 date
是 table 的主键,那么您必须确保每个结果行中的所有 date
值都相同:
select v.date, v1.value, v2.value
from values v, values v1, values v2
where v.date = v1.date and v.date = v2.date
and v1.indexVar = 6 and v2.indexVar = 2
或更好:
select v.date, v1.value, v2.value
from values v
inner join values v1 on (v1.date = v.date)
inner join values v2 on (v2.date = v.date)
where v1.indexVar = 6 and v2.indexVar = 2
如果主键是id
,那么对id
做同样的事情。 (你说你想根据日期对齐行,所以不确定哪一列最重要。)
您可以尝试使用伪造的聚合函数和组来减少过滤条件下的结果
SELECT date
, max(case when v.indexVar = 6 then v.values end) v1_value
, max(case when v.indexVar = 2 then v.values end) v2_value
FROM values
WHERE
date > 1548460800 AND indexVar = 6 OR indexVar = 2
group by date
你还应该添加一个合适的复合索引
create index idx1 on values ( indexVar, date)