如何才能完成两个巨大的MySQL表的连接?

时间:2016-10-19 10:00:18

标签: mysql join optimization

我有两张桌子

表1:

column1: varchar(20)
column2: varchar(20)
column3: varchar(20)

表2:

column1: varchar(20)
column2: varchar(20)
column3: varchar(20) <- empty
  • column1和column2在table1

  • 中都有单独的全文索引
  • 两个表都有2000万行

我需要通过匹配column3&amp;来填充table2 column1 column2table2column1&amp;来自column2的{​​{1}},然后从table1获取column3中的值,并将其放入table1的{​​{1}}。 column3&amp; table2可能不完全匹配,因此我使用的查询是:

column1

此查询永远不会完成。我让它运行了2周,仍然没有产生任何结果。它使用一个100%的CPU核心,几乎没有SSD IO,显然需要以某种方式进行优化。

我对任何有关查询优化,索引优化甚至DBMS优化(甚至迁移,如果它有帮助)的建议持开放态度,因为我需要在将来更频繁地进行这样的查询。

EDIT1

  

有很多优化指南,请使用谷歌。您可以增加config(InnoDB)中的线程。对于Update本身,我建议先创建一个temp_table,然后复制到db2

我知道但是用这些指南无法完全解决我的情景。我也知道,对于这个问题(巨大的数据库,性能,瓶颈,查询设计)的组合的所有可能排列的问题都存在,也在stackoverflow上。然而,直到今天,我无法弄清楚这个特定问题组合的最佳方法是什么,并希望在这里获得帮助。话虽如此: - 更多线程需要分片或分区才能使用多个CPU核心,如果我能用其他方法解决问题,我想避免 - 你怎么建议在这里创建这样的临时表?

  

如果不使用外卡字符,为什么要使用like运算符?用=替换它们。另外,在每个表中where条件的3列上是否有多列索引?请分享解释的输出,以及2个表中的任何现有索引。

  • 我在示例中留下了这些字符,但是一旦基本查询起作用就想使用它们,抱歉让人感到困惑。我不完全确定如何将这些通配符放入列比较中。
  • 我有两个单独的意义,我应该创建一个2列索引吗? (where条件中只有2列)
  • 您是想更好地解释我现在拥有的结构还是更喜欢用2列索引解释结构?
  

我猜你说数据库但是你在谈论桌子,对吗?

确切地说,抱歉这个混乱。

  

您编写的查询将执行20米x 20米的查找(对于表1中的每一行,查找表2中的所有行)。如果你有一个SSD或一个好的CPU,你就无法写入任何内容并期望它能够正常工作。如果你到了这一点,那么在开始编写SQL之前是时候考虑了。您需要做什么,您可以使用哪些工具以及您不知道的中间部分 - 这些是您每次发布400之前需要回答的问题十亿查询查询。

这就是我面临的情景。我不希望它像目前一样工作,说实话,所以我正在寻找可能使这个成为可解决方案的指针。基本&#34;更新它,匹配&#34;查询显然不适用于此处。所以我想找到一种更先进的解决方案。任何批评都是非常受欢迎的,所以感谢您的投入。你会怎么建议继续这里?

EDIT2

  

给我们一些样本值和非精确比较。

表1:

column2

表2:

UPDATE table1, table2 
SET table2.column3 = table1.column3 
WHERE table2.column1 LIKE table1.'%column1%' AND 
      table2.column2 LIKE table1.'%column2%';

这里,LIKE查询将填充表2的两行,如果它匹配&#34; Doe _&#34;为&#34; Doe&#34;。但是通过写下来,我只是意识到LIKE查询在这里没有选项,因为变量不会约束到表1中column2的后缀,而是需要各种可能的喜欢(两列的前导和尾随变体)在两个表中)。这反过来会增加所需匹配的数量。 所以,让我们忘记LIKE并专注于精确匹配。

  

FULLTEXT和LIKE彼此无关。

     

&#34;可能不完全匹配&#34; - 您将需要更多限制这种非限制。否则,任何查询尝试都将持续数周。

     

t2.c1 LIKE CONCAT(&#39;%&#39;,t1.c1,&#39;%&#39;)要求对t2的每一行检查t1行?这是400万亿次测试。没有硬件可以在合理的时间内完成。

     

FULLTEXT与&#34;单词&#34;一起使用。如果你的c1和c2是单词串,那么有一些希望使用FULLTEXT。 FULLTEXT比LIKE快得多,因为它具有基于单词的索引结构。

     

然而,即使FULLTEXT也没有接近t2.c1 = t1.c1的速度。仍然需要复合INDEX(c1,c2)然后它将是一个表的全表扫描(20M行),以及通过BTree索引到另一个表的20M探测。这就像40M操作 - 比LIKE好400T。

     

为了继续,请仔细考虑您的定义&#34;可能不完全匹配&#34;并展示你可以忍受的最佳。

好的,既然我决定放弃LIKE要求,你究竟打算用什么作为索引? 我这样读了你的帖子:

+---------+---------+-------------+---------+---------+---------+
| column1 | column2 | column3     | column4 | column5 | columnN |
+---------+---------+-------------+---------+---------+---------+
| John    | Doe_    | employee001 | xyz     | 12345   | ...     |
| Jim     | Doe     | employee002 | abc     | 67890   | ...     |
+---------+---------+-------------+---------+---------+---------+

这是对的吗?

但有两个后续问题: 1)您的意见中的更新是否像创建新表一样快,更快或更慢,即:

+---------+---------+---------+
| column1 | column2 | column3 |
+---------+---------+---------+
| John    | Doe     |         |
| Jim     | Doe     |         |
+---------+---------+---------+

2)indizes和/或匹配是否区分大小写?如果是,可以调整查询而无需更改column1&amp; column2到所有大写(或全部小写)?

2 个答案:

答案 0 :(得分:0)

t2.c1 LIKE CONCAT('%', t1.c1, '%')FULLTEXT彼此无关。

&#34;可能不完全匹配&#34; - 您将需要更多限制这种非限制。否则,任何查询尝试都将持续数周。

FULLTEXT要求针对t2的每一行检查t1行;那400个万亿测试。没有硬件可以在合理的时间内完成。

FULLTEXT适用于&#34;字&#34;。如果你的c1和c2是单词串,那么有一些希望使用LIKEFULLTEXTt2.c1 = t1.c1快得多,因为它具有基于单词的索引结构。

然而,即使INDEX(c1, c2)也不在LIKE的速度附近。仍然需要复合 WHERE CONCAT(t1.c1, t1.c2) = CONCAT(t2.c1, t2.c2)然后它将是一个表的全表扫描(20M行),以及通过BTree索引到另一个表的20M探测。这就像40M操作 - 比WHERE t1.c1=t2.c2 AND t1.c2 = t2.c2的400T好很多。

为了继续,请仔细考虑您的定义&#34;可能不完全匹配&#34;并展示你可以忍受的最佳。

修改

INDEX(c1,c2) 很多比说{{1}}更糟糕。后者将与{{1}}一起快速运行。

答案 1 :(得分:-1)

试试这个: 1.在db1和db2中添加一个新列,其中字符在column1和column2中永远不会出现,例如 @

ALTER TABLE `db1` ADD  `column4` VARCHAR(40) NOT NULL ;

UPDATE db1 SET column4 = column1 + '@' + column2

2。对db2执行相同的操作。然后在第4列(在db1和db2中)创建索引(BTREE)。

ALTER TABLE  `db1` ADD INDEX (  `column4` ) ;

ALTER TABLE  `db2` ADD INDEX (  `column4` ) ;

3。然后运行下一个查询:

UPDATE db1, db2 SET db2.column3 = db1.column3 WHERE db1.column4 = db2.column4;

它应该跑得足够快。 当它完成后 - 只需删除column4和它的索引