我有这样的查询:
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
)
)
我的表'doublon'
的结构如下:
id
etablissement_id
amenities_id
结构表是这样的:
我有2百万行,查询是慢,很多小时.. 有人知道如何优化这个查询以更快地执行它吗?
答案 0 :(得分:1)
首先,您的查询不正确。但是继续阅读,可能在答案结束时我发现了你需要这么奇怪的查询的原因。
让我们讨论最后一个子查询:
Select id
From `doublon`
group by etablissement_id,amenities_id
having Count(etablissement_id) = 1 and Count(amenities_id) = 1
只有在至少发生以下其中一项情况时,才能使用SELECT
查询GROUP BY
子句中的列:
GROUP BY
条款中; GROUP BY
子句中存在的列的值;例如,如果存在具有UNIQUE
索引的列(或表的UNIQUE
索引中存在的所有列)。列id
不适合 1 以上的任何情况。这使得查询illegal符合SQL
规范。
MySQL
接受它并努力为其生成结果集,但它在documentation中说:
...服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的,这可能不是您想要的。
HAVING
子句包含Count(etablissement_id)
和Count(amenities_id)
。当etablissement_id
和amenities_id
都不是 - NULL
时,这两个表达式具有相同的值,并且与COUNT(*)
(组中的行数)相同。它总是大于0
(一个组不能包含0
行)。
对于etablissement_id
或amenities_id
为NULL
时生成的组,相应的COUNT()
会返回0
。当两者同时为NULL
时,这也适用。
使用此信息,此查询将返回id
行,其组合(etablissement_id
,amenities_id
)在表中是唯一的(这些组只包含一行)和两个字段不是NULL
。
另一个GROUP BY
查询(使用此UNION
编辑)会从其组合(etablissement_id
,{amenities_id
,{}中返回不确定值 {1}})在表中不是唯一的(并且两个字段都不是NULL
),如文档中引用的片段中所述。
似乎UNION
从id
和etablissement_id
的每一组(amenities_id
,etablissement_id
)中挑选一个(随机)amenities_id
不是 - NULL
。外部SELECT
打算忽略id
选择的UNION
,并提供给DELETE
其他人。
(我认为甚至不需要中间SELECT
,您可以在WHERE
查询中使用其DELETE
子句。
我可以想象您需要运行此查询的唯一原因是表doublon
是correspondence table的many-to-many relationship
,它是在没有UNIQUE
索引的情况下创建的({3}} etablissement_id
,amenities_id
)(从相关表格导入的FOREIGN KEY
列)。
如果这是您的意图,那么有更简单的方法可以实现这一目标。
我会创建doublon
表的副本,使用正确的结构,然后我会使用DISTINCT
查询# 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
id
查询从左到右以原子方式操作重命名。避免停机很有用。
备注:强>
1 如果etablissement_id
列在功能上依赖于(amenities_id
,UNION
)对,那么SELECT
生成的所有组-ed查询包含单行。第一个SELECT
不会产生任何结果,第二个{{1}}将返回整个表格。
答案 1 :(得分:0)
如果没有错,这应该有效
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))