首页 > 解决方案 > SQL 无限加载

问题描述

我有一个包含 100 万条记录的数据库,使用JOIN、GROUP BY、ORDER进行简单查询的响应时间约为 1.2 秒。没关系,没有问题。我正在努力使用表别名来简化查询,但是当我使用两个或更多表别名执行简单查询时,请求永远不会结束并且 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;

数据: 示例

工作查询:

SELECT
    v.date,
    v.value
FROM
    `values` AS v
WHERE
    v.date > 1548460800 AND v.indexVar = 6 OR v.indexVar = 2

预期结果

无限加载查询:

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

预期结果

标签: mysqldatabasemariadbinfinite-loop

解决方案


您没有在查询中包含任何连接条件。

如果 values 表有 100 万行,那么将其包含两次会给您一个包含 100 万 * 100 万 = 1 万亿行的结果集。你正在应用一些条件,但你仍然会得到大量的结果。(并且您将值表包括了三遍!)

假设你有一个有一百万行的表,每一行只是一个从 1 到 100 万的整数。如果你这样做,select value from values where value > 900000那么你将获得 100,000 行。但是,如果您说select value from values v, values v2 where v.value > 900000对于与条件匹配的 100,000 行中的每一行,v.value > 900000您将从 v2 中获得所有百万行。即使您将相同的过滤器应用于 v2(即v2.value > 900000),查询仍将为原始值表中的每一行返回 100,000 个 v2 行——总共 100 亿行。

如果date是表的主键,那么您必须确保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. (你说你想根据日期对齐行,所以不确定哪一列最重要。)


推荐阅读