【问题标题】:How to compare two very large tables in MySQL?如何比较 MySQL 中的两个非常大的表?
【发布时间】:2015-02-19 22:11:39
【问题描述】:

我对 SQL 很陌生,所以我使用的是 MySQL 工作台,并且我有两个非常大的表(每个表大约 900K 行),我想比较这些表。请注意,两个表的行数相同。

每个表有 16 列,我只想比较其中的几列。因此,假设这些表有 DataID、a、b、c、d、e 列,我想查看基于 DataID 的每一行的表 A 和表 B 中的列 c 和 d 和 e 中的值是否相同。

在每个表中,我都有一个 DataID 列,作为比较每个表中的行的参考点,因此例如,我想将表 A 中 DataID=444 的行与表中具有相同 DataID 的行进行比较B,看看我感兴趣的列是否相同。

必须对所有 900k 行重复该过程,我想如果我可以将结果写在某处会有所帮助。

我会很感激任何帮助,如果我太困惑了,我很乐意回答任何问题。

【问题讨论】:

  • 你好。我们很乐意帮助您提供一些可以构建的代码。您当前的查询是什么样的?
  • 您好,除了使用简单的选择语句外,我对 SQL 并不十分精通。我想我知道需要做什么:我必须查看 A 中的 DataID = B 中的 DataID 的每个表,然后比较我感兴趣的列中的值是否相同。最后,我想显示行不同的 DataID。

标签: mysql comparison rows


【解决方案1】:

首先,要返回具有相同 DataID 并且在 c、d、e 中具有所有相同值的行表,请使用以下查询:

SELECT 
t1.c, t2.c, t1.d, t2.d, t1.e, t2.e
FROM
table1 t1
    INNER JOIN
table2 t2 ON t1.DataId = t2.DataId
WHERE
t1.c = t2.c AND t1.d = t2.d
    AND t1.e = t2.e

如果您想要任何值(c、d 或 e)相同的表,请在 WHERE 子句中使用 t1.c = t2.c or t1.d = t2.d or t1.e = t2.e。 要获取具有所有不同值的表,请在 WHERE 子句 t1.c <> t2.c AND t1.d <> t2.d AND t1.e <> t2.e 中使用以下内容 要获取任何值不同的表,请使用WHERE 子句t1.c <> t2.c OR t1.d <> t2.d OR t1.e <> t2.e
要保存结果,请使用以下查询:

INSERT INTO SaveTable SELECT 
t1.c, t2.c, t1.d, t2.d, t1.e, t2.e
FROM
table1 t1
    INNER JOIN
table2 t2 ON t1.DataId = t2.DataId
WHERE
t1.c <> t2.c AND t1.d <> t2.d AND t1.e <> t2.e

要在其他情况下添加插入值,只需修改 select 子句中的 where 子句和一个 just 值。

【讨论】:

  • 嗨,非常感谢。这似乎“有效”。引号是因为我认为由于大量数据,查询错误“错误 2013 在查询期间丢失了与 mysql 服务器的连接”。有没有办法以某种方式分解这个查询,所以它不会对 MySQL 造成太大的压力?
  • 我的查询INSERT INTO mt_vs_us SELECT t1.RunID, t1.CaseID, t1.DataID, t1.OrderNumber, t1.CategoryCode, t1.COD, t1.Region, t1.PostalCode, t1.SalePrice, t1.CDN, t1.Tax, t1.IntShipping, t1.IntHandling, t1.Duty, t1.Brokerage, t1.OrderData, t1.Ref, t1.RunDate, t1.Status, t1.Details FROM order_results_mt t1 INNER JOIN order_results_us t2 ON t1.DataId = t2.DataId WHERE t1.Tax &lt;&gt; t2.Tax or t1.IntShipping &lt;&gt; t2.IntShipping or t1.IntHandling &lt;&gt; t2.IntHandling or t1.Duty &lt;&gt; t2.Duty or t1.Brokerage &lt;&gt; t2.Brokerage
  • 您可以尝试分段进行此查询。我的意思是 DataId 从 1 到 10000,从 1001 到 2000 等等。或者尝试在设置中增加查询工作时间。
  • 我明白了,我去看看!我在mysql中的ibdata1文件增长并占用大量磁盘空间(此时为60 GB)的过程中遇到了一个10年的MySQL错误
【解决方案2】:

如果我理解正确,您只需要那些 DataID、c、d 和 e 列具有相同值的记录。 在这种情况下,以下语句将为您提供结果:

SELECT TableA.DataID, 
TableA.c, 
TableA.d, 
TableA.e 
-- add any other columns to the selection list if needed

INTO result_table
FROM TableA 
INNER JOIN TableB
ON TableA.DataID = TableB.DataID
WHERE TableA.c = TableB.c
AND TableA.d = TableB.d
AND TableA.e = TableB.e

据我所知,没有比使用简单的 INNER JOIN 语句解决这个问题更好的方法(从性能的角度来看)。 假设 DataID 是 TableA 和 TableB 中的主键,即使在巨大的数据集上也应该很快。

【讨论】:

  • 您的插入语法有误。请参阅下面的答案。
  • 是的,但是我没有编辑它,因为您已经添加了答案,只是一个小注释:当 A 和 B 表的列具有相同的值时,为什么要插入它们那些列?我认为如果我们只存储 TableA 中的列会节省一些空间和时间
  • 没错,我在写插入片段时考虑到了所有不同的值,这样会更相关。
【解决方案3】:

您可以使用内连接来比较数据

一个小的 sn-p 会是

SELECT table_A.a, table_B.a, ...... 
FROM table_A
INNER JOIN table_B
  ON table_A.DataID = table_B.DataID;

【讨论】:

    【解决方案4】:

    你可以大大简化这个任务,但是你会读取很多数据。如果没问题,只需执行 2 个 SELECT,并计算它们的 MD5。然后就可以比较MD5了。

    在 Linux 上从命令行客户端获取 Md5 非常简单:

    \P md5sum
    SELECT ...
    

    通过程序来做会有点长,但毕竟你只需要2个循环。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-02
      • 2013-03-03
      • 1970-01-01
      • 1970-01-01
      • 2012-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多