0

这是一场长达 19 小时的噩梦。

我有一个非常大的查询,本质上需要跨几个表连接大型数据集。进行连接后,我需要使用 select 语句中的数据更新原始表。SELECT 语句超级快,而 UPDATE 语句超级慢。

这是选择语句。

SELECT l.col1,
       l.col2,
       l.col3,
       p.personid
FROM table1 p
LEFT JOIN table2 l ON (l.col1 = p.col1)
LEFT JOIN
  (SELECT name,
          col AS 'col2'
   FROM tbl3 f
   WHERE f.col LIKE '%-F') pcf ON (pcf.col1 = p.col1)
LEFT JOIN
  (SELECT name,
          col AS 'col3'
   FROM tbl4 f
   WHERE f.col LIKE '%-M') pcm ON (pcm.col1 = p.col1)
WHERE p.requestid = '1928'

现在,如果我采用 EXACT SAME 系列的 JOIN 并将其放入 UPDATE 上下文中,则查询将永远存在。

UPDATE table1 p
LEFT JOIN table2 l ON (l.col1 = p.col1)
LEFT JOIN
  (SELECT name,
          col AS 'col2'
   FROM tbl3 f
   WHERE f.col LIKE '%-F') pcf ON (pcf.col1 = p.col1)
LEFT JOIN
  (SELECT name,
          col AS 'col3'
   FROM tbl4 f
   WHERE f.col LIKE '%-M') pcm ON (pcm.col1 = p.col1)
SET p.col1 = l.col1,
    p.col2 = l.col2,
    p.col3 = l.col3
WHERE p.requestid = '1928'

那么...为什么 UPDATE JOIN 语句比 SELECT JOIN 语句花费的时间要长这么多?时间更长。而且我已经尝试过临时表,但它没有用。

仅供参考,我正在使用 50k 或更多记录的表。

如果您对 EXPLAIN 结果感到好奇,这就是我 EXPLAIN 选择查询时发生的情况(尽管显然您不能使用 explain 进行更新?)

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY p   ALL NULL    NULL    NULL    NULL    613246  Using where
1   PRIMARY l   eq_ref  PRIMARY,name_3,name,name_2  PRIMARY 257 drilldev_db.p.lastname  1   
1   PRIMARY <derived2>  ALL NULL    NULL    NULL    NULL    23435   
1   PRIMARY <derived3>  ALL NULL    NULL    NULL    NULL    13610   
1   PRIMARY <derived4>  ALL NULL    NULL    NULL    NULL    13053   
1   PRIMARY <derived5>  ALL NULL    NULL    NULL    NULL    8273    
1   PRIMARY <derived6>  ALL NULL    NULL    NULL    NULL    11481   
1   PRIMARY <derived7>  ALL NULL    NULL    NULL    NULL    6708    
1   PRIMARY <derived8>  ALL NULL    NULL    NULL    NULL    9588    
1   PRIMARY <derived9>  ALL NULL    NULL    NULL    NULL    5494    
1   PRIMARY <derived10> ALL NULL    NULL    NULL    NULL    6981    
1   PRIMARY <derived11> ALL NULL    NULL    NULL    NULL    4107    
1   PRIMARY <derived12> ALL NULL    NULL    NULL    NULL    5973    
1   PRIMARY <derived13> ALL NULL    NULL    NULL    NULL    3851    
1   PRIMARY <derived14> ALL NULL    NULL    NULL    NULL    4935    
1   PRIMARY <derived15> ALL NULL    NULL    NULL    NULL    3574    
1   PRIMARY <derived16> ALL NULL    NULL    NULL    NULL    5793    
1   PRIMARY <derived17> ALL NULL    NULL    NULL    NULL    4706    
17  DERIVED f   ref year,gender gender  257     364263  Using where; Using temporary; Using filesort
16  DERIVED f   ref year,gender gender  257     397322  Using where; Using temporary; Using filesort
15  DERIVED f   range   year,gender year    4   NULL    54092   Using where; Using temporary; Using filesort
14  DERIVED f   range   year,gender year    4   NULL    54092   Using where; Using temporary; Using filesort
13  DERIVED f   range   year,gender year    4   NULL    62494   Using where; Using temporary; Using filesort
12  DERIVED f   range   year,gender year    4   NULL    62494   Using where; Using temporary; Using filesort
11  DERIVED f   range   year,gender year    4   NULL    69317   Using where; Using temporary; Using filesort
10  DERIVED f   range   year,gender year    4   NULL    69317   Using where; Using temporary; Using filesort
9   DERIVED f   ref year,gender gender  257     364263  Using where; Using temporary; Using filesort
8   DERIVED f   range   year,gender year    4   NULL    94949   Using where; Using temporary; Using filesort
7   DERIVED f   ref year,gender gender  257     364263  Using where; Using temporary; Using filesort
6   DERIVED f   ref year,gender gender  257     397322  Using where; Using temporary; Using filesort
5   DERIVED f   ref year,gender gender  257     364263  Using where; Using temporary; Using filesort
4   DERIVED f   ref year,gender gender  257     397322  Using where; Using temporary; Using filesort
3   DERIVED f   ALL NULL    NULL    NULL    NULL    37045   Using where
2   DERIVED f   ALL NULL    NULL    NULL    NULL    37045   Using where

谢谢!

-b

4

2 回答 2

0

如果这是您的实际语句,则不需要第二个和第三个 LEFT JOIN,因为它们不会改变结果。

顺便说一句,不知道 MySQL 能够有效地处理“复杂”查询 :-) 如果您在临时表中实现 SELECT 的结果并使用它来代替它应该会快得多。

于 2013-08-29T19:32:22.463 回答
0

让我们考虑一下。如果您正在选择表格的行(只是抓取它们)而不是在浏览它们时更新每个...单个...行,那么需要更长的时间吗?读取 n 行或修改(更新) n 行?

将其与阅读一本书的 10 行与在一张纸上写相同的 10 行进行比较。哪个需要更长的时间?

我还可以补充一点,您阅读的行与更新的行越多,差异就会越大。正如一本书的阅读和写作行数会有更大的差异一样,你读/写的行数越多。

于 2013-08-29T18:30:20.773 回答