mysql - 在MySQL上优化查询SQL

标签 mysql sql indexing

我有这样的查询:

 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_idamenities_id都不是-NULL时,这两个表达式具有相同的值,并且与COUNT(*)(组中的行数)相同。并且它总是大于0(组不能包含0行)。

对于etablissement_idamenities_idNULL时生成的组,相应的COUNT()返回0。当两者同时为NULL时,这也适用。

使用此信息,该查询返回行的id,其组合(etablissement_idamenities_id)在表中是唯一的(组仅包含一行),并且两个字段都不是NULL

另一个GROUP BY查询(与此查询一起为UNION)从表中组合(etablissement_idamenities_id)不唯一(并且两个字段都不是< cc>),如文档中引用的片段所述。

似乎NULL从(UNIONid)的每组中选择一个(随机)etablissement_id,其中amenities_idetablissement_id都不是-amenities_id。外部的NULL打算忽略SELECT选择的id,并将其余的提供给UNION

(我认为甚至不需要中间DELETE,您可以在SELECT查询中使用其WHERE子句)。

我可以想象您需要运行此查询的唯一原因是表DELETEcorrespondence tabledoublon,该many-to-many relationship是在(UNIQUEetablissement_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列在功能上取决于(DISTINCTRENAME)对,则id -ed查询生成的所有组都包含一行。第一个etablissement_id将不会产生任何结果,第二个amenities_id将返回整个表。

关于mysql - 在MySQL上优化查询SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29034450/

相关文章:

MySQL ID 增量难题

MySQL:返回多个匹配项

sql - 数据库插入机制

java - 数据库文件结构和索引及实现

mysql - 在 Apache Solr 中索引 MySQL

curl - Flume/Elasticsearch创建新索引并忽略显式创建的索引

php - mysql select * from table where a 列值 = b 列值 laravel

mysql - 如何使用 "sync"/revision-control 整个 mysql 数据库以及所有 git 提交和 checkout ?

java - PostgreSQL + Java

c# - 如何在脚本组件中访问 ssis 包变量