我有这样的查询:
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
结构表是这样的:
http://hpics.li/bbb5eda
我有200万行,查询很慢,很多小时..
有人知道如何优化此查询以更快地执行吗?
SqlFiddle
最佳答案
首先,您的查询不正确。但是请继续阅读,到答案的最后,我可能发现了您需要这样一个奇怪查询的原因。
让我们讨论最后一个子查询:
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
子句中;它用作aggregate function的参数;
该列的值在功能上取决于
GROUP BY
子句中存在的列的值;例如,如果存在具有UNIQUE
索引的列(或表的UNIQUE
索引中存在的所有列)。id
列不适合以上任何一种情况。这将根据SQL
规范进行查询illegal。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
)不唯一(并且两个字段都不是< cc>),如文档中引用的片段所述。似乎
NULL
从(UNION
,id
)的每组中选择一个(随机)etablissement_id
,其中amenities_id
和etablissement_id
都不是-amenities_id
。外部的NULL
打算忽略SELECT
选择的id
,并将其余的提供给UNION
。(我认为甚至不需要中间
DELETE
,您可以在SELECT
查询中使用其WHERE
子句)。我可以想象您需要运行此查询的唯一原因是表
DELETE
是correspondence table的doublon
,该many-to-many relationship
是在(UNIQUE
,etablissement_id
)(< cc>从相关表中导入的列)。如果这是您的意图,那么可以使用更简单的方法来实现此目标。
我将使用正确的结构创建
amenities_id
表的副本,然后使用带有FOREIGN KEY
的查询:
# 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`;
doublon
查询从左到右原子地操作重命名。避免停机很有用。笔记:
1如果
INSERT ... SELECT
列在功能上取决于(DISTINCT
,RENAME
)对,则id
-ed查询生成的所有组都包含一行。第一个etablissement_id
将不会产生任何结果,第二个amenities_id
将返回整个表。
关于mysql - 在MySQL上优化查询SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29034450/