慢复合mysql更新查询

时间:2012-07-01 21:59:30

标签: mysql

我们正在两个数据库表之间进行更新查询,速度非常慢。如下所示:执行查询需要30

一个表,lab.list,包含大约940,000条记录,另一个,mind.list大约3,700,000(370万) 当满足两个BETWEEN条件时,更新设置字段。这是查询:

UPDATE lab.list L , mind.list M SET L.locId = M.locId  WHERE L.longip BETWEEN M.startIpNum AND M.endIpNum AND L.date BETWEEN "20100301" AND "20100401" AND L.locId = 0

就像现在一样,查询每8秒执行大约1次更新。

我们也在同一个数据库中使用mind.list表进行了尝试,但这与查询时间无关。

UPDATE lab.list L, lab.mind M  SET L.locId = M.locId  WHERE  longip BETWEEN M.startIpNum AND M.endIpNum AND date BETWEEN "20100301" AND "20100401" AND L.locId = 0;

有没有办法加快这个查询?基本上恕我直言,它应该使数据库的两个子集: mind.list.longip BETWEEN M.startIpNum和M.endIpNum lab.list.date BETWEEN“20100301”和“20100401”

然后更新这些子集的值。在某个地方,我认为我犯了一个错误,但在哪里?也许有更快的查询可能吗?

我们尝试了log_slow_queries,但这表明它确实检查了数百万行,可能会一直上升到3331 gigarows。

技术信息:

  • 服务器版本:5.5.22-0ubuntu1-log(Ubuntu)
  • lab.list在locId,longip,date
  • 上有索引
  • lab.mind在locId,startIpNum和M.endIpNum上有索引
  • 硬件:2x至3.4 GHz,4GB RAM,128 GB SSD(这应该不是问题!)

2 个答案:

答案 0 :(得分:1)

我首先尝试按此顺序对startIpNum,endIpNum,locId进行索引。即使用于更新,locId也不会用于SELECTing。

出于同样的原因,我在locId,date和longip(在第一个分块中没有使用,这应该在日期运行)上对此命令进行索引。

那么为startIpNum和endIpNum分配了哪种数据类型?对于IPv4,最好转换为INTEGER并使用INET_ATON和INET_NTOA进行用户I / O.我假设你已经这样做了。

要运行更新,您可能会尝试使用临时表对M数据库进行分段。那就是:

* select all records of lab in the given range of dates with locId = 0 into a temporary table TABLE1.
* run an analysis on TABLE1 grouping IP addresses by their first N bits (using AND with a suitable mask: 0x80000000, 0xC0000000, ... 0xF8000000... and so on, until you find  that you have divided into a "suitable" number of IP "families". These will, by and large, match with startIpNum (but that's not strictly necessary).
* say that you have divided in 1000 families of IP.
* For each family:
*    select those IPs from TABLE1 to TABLE3.
*    select the IPs matching that family from mind to TABLE2.
*    run the update of the matching records between TABLE3 and TABLE2. This should take place in about one hundred thousandth of the time of the big query.
*    copy-update TABLE3 into lab, discard TABLE3 and TABLE2.
* Repeat with next "family".

这不是很理想,但如果略微改进的索引没有帮助,我真的看不到那么多选项。

答案 1 :(得分:0)

最后,查询太大或太麻烦,无法填充mysql。索引后即使。在高端Sybase服务器上使用相同的数据测试相同的查询也需要3个小时。

所以我们放弃了在数据库服务器上做到这一切的想法,然后又回到了脚本语言。

我们在python中做了以下事情:

  1. 加载370万条记录中的100000条记录,然后循环遍历行
  2. 对于每一行,设置locId并填写其余列
  3. 所有这些更新一起大约需要5分钟,所以这是一个巨大的进步!

    结论:

      

    在数据库框之外思考!