【问题标题】:Select remaining records from two tables (tableB - tableA)从两个表中选择剩余的记录(tableS - tableS)
【发布时间】:2014-07-08 16:35:38
【问题描述】:

如何选择tableB中存在但tableA中不存在的记录(基本上就像tableB-tableA)?

我有以下表格:(每个表格有 100 万条记录)

tableA
    id int(11) NOT NULL PRIMARY KEY
    name varchar(50)
    sku varchar(10) index
    description text

tableB
    id int(11) NOT NULL PRIMARY KEY
    stock int(11)
    price int(11)
    sku varchar(10) index

注意:sku 已编入索引。

  1. tableA 和 tableB 在 sku 字段中是一对一的关系。
  2. 两个表都有 1m 条记录
  3. 我想获取存在于tableB 但不在tableA 中的记录(基本上它就像tableB - tableA)。 LEFT JOIN 而不是 IN 很糟糕(非常慢)。

有什么替代解决方案?

以下是我尝试过的查询:

LEFT JOIN query:
    SELECT a.sku FROM tableA a
    LEFT JOIN tableB b
       ON a.sku = b.sku 
    WHERE a.sku is NULL

NOT IN query:
    SELECT * from tableB where sku NOT IN (SELECT sku from tableA)

【问题讨论】:

  • 你好草莓,我添加了完整的表定义(已编辑问题)
  • id 是主键,两者都是 VARCHAR (10) 抱歉我的错字,让我编辑我的问题

标签: mysql


【解决方案1】:

我认为最好的解决方案是left join 或:

select *
from tableB b
where not exists (select 1 from tableA where a.sku = b.sku);

not in 解决方案的问题是tableA 中的NULL 值将导致查询中不返回任何行。

为了提高性能,您需要在tableA(sku) 上建立索引:

create index tableA_sku on tableA(sku);

这将加快left joinnot exists 版本的速度。

【讨论】:

  • Gorden,和 NOT IN 一样慢
  • 你认为什么是“慢”?它确实必须检查一百万条记录。
  • 需要 1 小时。超过 3 分钟,我会认为很慢
  • @KrishnaSunuwar 。 . .这是非常不合理的,尤其是索引。
  • 好的,可以选择什么,所以它不需要一个小时。让我们说5分钟左右。应该有一些解决方案,因为很多大数据分析都是在 MySQL 中完成的,100 万对大数据来说不算什么,因为它们可以处理数十亿(或更多记录)
【解决方案2】:

准备环境以复制问题:

DELIMITER $$

DROP PROCEDURE IF EXISTS `insertMe` $$
CREATE PROCEDURE insertMe()
BEGIN
 DECLARE i BIGINT DEFAULT 2;
  WHILE (i <= 1000000) DO
   INSERT INTO tableA(id,NAME,sku,description) VALUES(i,CONCAT('name',i),CONCAT('sku',i),CONCAT('description',i));  
   IF(i%2=0) THEN
       INSERT INTO tableB(id,stock,price,sku) VALUES(i,i%10,i%5,CONCAT('sku',i)); 
       END IF;
   SET i=i+1;
 END WHILE;
/*
CALL insertMe();
*/
END $$

DELIMITER ;

CREATE INDEX idx_tableA ON tableA(sku);
CREATE INDEX idx_tableB ON tableB(sku);

在我的测试环境(2 个虚拟 CPU 和 1G RAM)中,查询(使用左连接)已在 1-2 秒内执行完毕。

@Gordon Linoff 提到的左连接查询和查询没有任何问题,我建议按照 GordonL 的建议通过执行来验证索引的使用情况。

接下来,我怀疑 MYSQL 数据库中的陈旧表统计信息存在性能问题。请尝试以下脚本,然后查看查询的性能。

ANALYZE TABLE tableA;
ANALYZE TABLE tableB;

最后但同样重要的是,尝试备份/重新创建两个表及其索引以及上述分析语句,然后查看查询的性能。它修复了行链接和迁移的问题。

【讨论】:

    猜你喜欢
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多