在 mysql 上优化查询 sql
Optimise query sql on mysql
我有这样的查询:
DELETE FROM doublon WHERE id in
( Select id from `doublon` where `id` not in
( Select id
From `doublon`
group by etablissement_id,amenities_id
having Count(etablissement_id) > 1 and Count(amenities_id) > 1
union
Select id
From `doublon`
group by etablissement_id,amenities_id
having Count(etablissement_id) = 1 and Count(amenities_id) = 1
)
)
我的table'doublon'
的结构是这样的:
id
etablissement_id
amenities_id
结构table是这样的:
我有 200 万行,查询速度很慢,很多小时..
有人知道如何优化此查询以更快地执行吗?
如果我没记错的话应该可以
DELETE FROM doublon
WHERE id IN (SELECT id
FROM doublon
WHERE id NOT IN (SELECT id
FROM doublon
GROUP BY etablissement_id,
amenities_id
HAVING Count(etablissement_id) >= 1
AND Count(amenities_id) >= 1))
首先,您的查询不正确。但请继续阅读,可能在回答结束时我发现了您需要这种奇怪查询的原因。
让我们讨论最后一个子查询:
Select id
From `doublon`
group by etablissement_id,amenities_id
having Count(etablissement_id) = 1 and Count(amenities_id) = 1
您可以在具有 GROUP BY
的查询的 SELECT
子句中使用列,前提是至少发生以下情况之一:
- 它也出现在
GROUP BY
子句中;
- 它被用作aggregate function的参数;
- 该列的值在功能上取决于
GROUP BY
子句中存在的列的值;例如,如果存在具有 UNIQUE
索引的列(或存在于 table 的 UNIQUE
索引中的所有列)。
第 id
列不符合上述任何情况1。这使得查询 illegal 根据 SQL
规范。
然而,MySQL
接受它并努力为其生成结果集,但它在 documentation:
中表示
... the server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate, which is probably not what you want.
HAVING
子句包含 Count(etablissement_id)
和 Count(amenities_id)
。当 etablissement_id
和 amenities_id
都不是 -NULL
时,这两个表达式具有相同的值并且与 COUNT(*)
(组中的行数)相同。它总是大于 0
(一个组不能包含 0
行)。
对于etablissement_id
或amenities_id
为NULL
时生成的组对应的COUNT()
returns0
。这也适用于两者同时 NULL
的情况。
使用此信息,此查询 return 行的 id
行的组合(etablissement_id
、amenities_id
)在 table 中是唯一的(这些组只包含一行)并且两个字段都不是 NULL
.
其他 GROUP BY
查询(即 UNION
-ed 与此查询)returns 来自行组的不确定值其组合 (etablissement_id
、amenities_id
) 在 table 中不是唯一的(并且两个字段都不是 NULL
),如文档中引用的片段中所述。
似乎 UNION
从每组 (etablissement_id
, amenities_id
) 中选择一个(随机)id
,其中 etablissement_id
和 amenities_id
不是-NULL
。外层 SELECT
打算忽略 UNION
选择的 id
并提供给 DELETE
其余的。
(我认为甚至不需要中间的 SELECT
,您可以在 DELETE
查询中使用它的 WHERE
子句)。
我能想象你需要 运行 这个查询的唯一原因是 table doublon
是在没有 UNIQUE
的情况下创建的 correspondence table of a many-to-many relationship
索引 (etablissement_id
, amenities_id
)(从相关 table 导入的 FOREIGN KEY
列)。
如果这是你的意图那么有更简单的方法可以实现这个目标。
我将使用正确的结构创建 doublon
table 的副本,然后我将使用带有 DISTINCT
的 INSERT ... SELECT
查询从旧的 table 需要的值。然后我会交换 tables 并删除旧的。
查询:
# Create the new table
CREATE TABLE `doublon_fixed` LIKE `doublon`;
# Add the needed UNIQUE INDEX
ALTER TABLE `doublon_fixed`
ADD UNIQUE INDEX `etablissement_amenities`(`etablissement_id`, `amenities_id`);
# Copy the needed values
INSERT INTO `doublon_fixed` (`etablissement_id`, `amenities_id`)
SELECT DISTINCT `etablissement_id`, `amenities_id`
FROM `doublon`;
# Swap the tables
RENAME TABLE `doublon` TO `doublon_old`, `doublon_fixed` TO `doublon`;
# Remove the old table
DROP TABLE `doublon_old`;
RENAME
查询以原子方式从左到右操作重命名。避免停机很有用。
备注:
1 如果 id
列在功能上依赖于 (etablissement_id
, amenities_id
) 对,则由UNION
-ed 查询包含一行。第一个 SELECT
不会产生任何结果,第二个 SELECT
将 return 整个 table).
我有这样的查询:
DELETE FROM doublon WHERE id in
( Select id from `doublon` where `id` not in
( Select id
From `doublon`
group by etablissement_id,amenities_id
having Count(etablissement_id) > 1 and Count(amenities_id) > 1
union
Select id
From `doublon`
group by etablissement_id,amenities_id
having Count(etablissement_id) = 1 and Count(amenities_id) = 1
)
)
我的table'doublon'
的结构是这样的:
id
etablissement_id
amenities_id
结构table是这样的:
我有 200 万行,查询速度很慢,很多小时.. 有人知道如何优化此查询以更快地执行吗?
如果我没记错的话应该可以
DELETE FROM doublon
WHERE id IN (SELECT id
FROM doublon
WHERE id NOT IN (SELECT id
FROM doublon
GROUP BY etablissement_id,
amenities_id
HAVING Count(etablissement_id) >= 1
AND Count(amenities_id) >= 1))
首先,您的查询不正确。但请继续阅读,可能在回答结束时我发现了您需要这种奇怪查询的原因。
让我们讨论最后一个子查询:
Select id
From `doublon`
group by etablissement_id,amenities_id
having Count(etablissement_id) = 1 and Count(amenities_id) = 1
您可以在具有 GROUP BY
的查询的 SELECT
子句中使用列,前提是至少发生以下情况之一:
- 它也出现在
GROUP BY
子句中; - 它被用作aggregate function的参数;
- 该列的值在功能上取决于
GROUP BY
子句中存在的列的值;例如,如果存在具有UNIQUE
索引的列(或存在于 table 的UNIQUE
索引中的所有列)。
第 id
列不符合上述任何情况1。这使得查询 illegal 根据 SQL
规范。
MySQL
接受它并努力为其生成结果集,但它在 documentation:
... the server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate, which is probably not what you want.
HAVING
子句包含 Count(etablissement_id)
和 Count(amenities_id)
。当 etablissement_id
和 amenities_id
都不是 -NULL
时,这两个表达式具有相同的值并且与 COUNT(*)
(组中的行数)相同。它总是大于 0
(一个组不能包含 0
行)。
对于etablissement_id
或amenities_id
为NULL
时生成的组对应的COUNT()
returns0
。这也适用于两者同时 NULL
的情况。
使用此信息,此查询 return 行的 id
行的组合(etablissement_id
、amenities_id
)在 table 中是唯一的(这些组只包含一行)并且两个字段都不是 NULL
.
其他 GROUP BY
查询(即 UNION
-ed 与此查询)returns 来自行组的不确定值其组合 (etablissement_id
、amenities_id
) 在 table 中不是唯一的(并且两个字段都不是 NULL
),如文档中引用的片段中所述。
似乎 UNION
从每组 (etablissement_id
, amenities_id
) 中选择一个(随机)id
,其中 etablissement_id
和 amenities_id
不是-NULL
。外层 SELECT
打算忽略 UNION
选择的 id
并提供给 DELETE
其余的。
(我认为甚至不需要中间的 SELECT
,您可以在 DELETE
查询中使用它的 WHERE
子句)。
我能想象你需要 运行 这个查询的唯一原因是 table doublon
是在没有 UNIQUE
的情况下创建的 correspondence table of a many-to-many relationship
索引 (etablissement_id
, amenities_id
)(从相关 table 导入的 FOREIGN KEY
列)。
如果这是你的意图那么有更简单的方法可以实现这个目标。
我将使用正确的结构创建 doublon
table 的副本,然后我将使用带有 DISTINCT
的 INSERT ... SELECT
查询从旧的 table 需要的值。然后我会交换 tables 并删除旧的。
查询:
# Create the new table
CREATE TABLE `doublon_fixed` LIKE `doublon`;
# Add the needed UNIQUE INDEX
ALTER TABLE `doublon_fixed`
ADD UNIQUE INDEX `etablissement_amenities`(`etablissement_id`, `amenities_id`);
# Copy the needed values
INSERT INTO `doublon_fixed` (`etablissement_id`, `amenities_id`)
SELECT DISTINCT `etablissement_id`, `amenities_id`
FROM `doublon`;
# Swap the tables
RENAME TABLE `doublon` TO `doublon_old`, `doublon_fixed` TO `doublon`;
# Remove the old table
DROP TABLE `doublon_old`;
RENAME
查询以原子方式从左到右操作重命名。避免停机很有用。
备注:
1 如果 id
列在功能上依赖于 (etablissement_id
, amenities_id
) 对,则由UNION
-ed 查询包含一行。第一个 SELECT
不会产生任何结果,第二个 SELECT
将 return 整个 table).