通过LEFT JOIN优化SQL子查询

时间:2015-09-16 18:32:17

标签: mysql join subquery sql-insert notin

我想根据uniqueEntries中不存在的actualEntries User_ID将actualEntries表中的所有记录插入到uniqueEntries表中。

我开始使用包含$ awk -v RS='\t' '/Target/{print NR; exit}' file.tsv 3 子查询的sql子句,这个子查询非常慢(在400K记录上运行时),并将其转换为@Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Autowired private MyWebSocketHandler webSocketHandler; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(webSocketHandler, "/"); } } 子句,但速度没有提高。 / p>

以下是包含NOT IN子查询的原始sql子句:

LEFT JOIN

以下是转换为NOT IN后的sql子句:

INSERT INTO uniqueEntries 
  SELECT * 
  FROM actualEntries 
  WHERE actualEntries.User_ID NOT IN (
    SELECT uniqueEntries.User_ID 
    FROM uniqueEntries
  )
  GROUP BY User_ID"

当我在50条记录上运行两个查询时,它们立即完成,但是当我在400K记录上运行它们时,它们没有完成。

完成此操作的最快方法是什么?

更新/解决方案: 根据@ Rahul,@ Steve E和@fhthiella,我更新了LEFT JOIN,如下所示,并将470K记录的处理时间减少到2分钟。

LEFT JOIN

3 个答案:

答案 0 :(得分:2)

在uniqueEntries.User_ID上放置唯一键或主键。然后

INSERT IGNORE INTO uniqueEntries 
  SELECT actualEntries.* 
  FROM actualEntries

IGNORE子句将使MySQL在插入过程中跳过错误。 这就是the manual所说的:

  

如果使用IGNORE关键字,则会出错   执行INSERT语句时发生的操作将被忽略。对于   例如,没有IGNORE,是一个复制现有UNIQUE的行   表中的index或PRIMARY KEY值会导致重复键错误   声明中止。使用IGNORE,行被丢弃,没有   发生错误。但是,忽略的错误可能会产生警告   重复键错误没有。

答案 1 :(得分:1)

首先删除GROUP BY子句GROUP BY User_ID,因为根本不需要它。此外,对于表User_IDuniqueEntries,您应该在actualEntries列上有索引,因为您将其用作连接列。这样,您的查询应该看起来像

INSERT INTO uniqueEntries 
  SELECT actualEntries.* 
  FROM actualEntries 
  LEFT JOIN uniqueEntries 
  ON uniqueEntries.User_ID = actualEntries.User_ID 
  WHERE uniqueEntries.User_ID IS NULL 

答案 2 :(得分:1)

您应该在uniqueEntries.User_ID和actualEntries.User_ID字段上添加索引:

ALTER TABLE uniqueEntries ADD INDEX idx_ue_id (User_ID);
ALTER TABLE actualEntries ADD INDEX idx_ae_id (User_ID);

这应该使连接更快。我还看到你正在选择所有表格字段:

SELECT actualEntries.*

但是你按User_id进行分组

GROUP BY User_ID

我认为你这样做是因为每个User_ID可能有多行。 MySQL允许您这样做,但请注意,如果有多行,您的查询将只保留一行,但未分组的值将不确定(它们可以属于任何分组行)。