2012-01-17 42 views
2

我有一个事件数据库,每天晚上都会更新。单个事件包含三个(或更多)表中的信息。最近更新量已经导致我的MySQL引擎非常慢,直到我插入新事件时,其他查询被冻结。为了加快速度,我想进行一系列批量查询,而不是分别执行每个批量查询,而我认为这是很大一部分开销。棘手的MySQL批量查询

的问题是,因为数据在多个表传播,这是我必须做的,插入一个事件:

(in Mysql) INSERT INTO 'locations' (...) VALUES (...) ON DUPLICATE KEY UPDATE ... 
    (in php get the last inserted id into variable $locationID) 
    (in Mysql) INSERT INTO 'event_info' (...) VALUES ($locationID, ...) ON DUPLICATE KEY UPDATE... 
    (in php get the last inserted id into variable $eventID) 
    (in Mysql) INSERT INTO 'event_times' (...) VALUES ($eventID, ...) ON DUPLICATE KEY UPDATE... 

我不是在设计表中寻求帮助,但你可以看到插入单个事件需要至少三个插入,每个插入取决于从前一个获取id。这就是为什么我不知道从哪里开始将其作为批量请求。将这个过程设计成批量请求的任何帮助都会很棒,谢谢!

编辑:我可能已经有位置或事件信息之前,这就是为什么在上的重复密钥更新的部分是有这样,如果它已经在数据库中,我得到旧的标识。我不知道,直到插入,如果它是新的数据,或者它已经存在于数据库中。 (因为这一点,除非我误解,否则我不能做预先分配ID的事情,因为每次都假设一个新ID。)

+0

你在使用什么数据库引擎?请记住,MyISAM为每个插入锁定表。 – 2012-01-17 22:30:41

+0

这是MyISAM,但其他​​查询被冻结到一个完全不同的表,而不是这会影响,所以我认为这只是所有插入和索引更新的整体应变。 – hackartist 2012-01-17 22:39:58

回答

2

不要使用自动递增列 - 在插入前预先分配您的引用ID。这样你可以使用批量插入并删除依赖项。

更新:

  1. 选择任何现有的ID从数据库(理想的是单一选择为所有已知的数据)。

  2. 丰富数据以插入任何已知的ID。 (为每个项目计算一个关键字,这些关键字将与数据库中的表的主键相对应,使用该关键字更新数据库中具有id的项目) - 您希望最终将数据拆分为您知道的项目数据库,因此有一个已知的ID - 和数据库中不存在的数据,因此需要一个密钥分配。我假设你的表有一个不仅仅是id的主键 - 否则数据库如何知道你已经拥有数据库中的数据。

  3. 将新ID分配给没有ID的任何记录。

  4. 批量替换数据库中的数据(用单条语句插入多行)。

+0

有趣的是,我会怎么做?问题是这个位置可能是我已经拥有的位置,并且直到ON DUPLICATED KEY UPDATE部分发生,我不知道它是否是新的或不是... – hackartist 2012-01-17 21:12:11

+1

将您的INSERT INTO更改为REPLACE INTO - 然后它会自动更新当你的主键匹配时。 – 2012-01-17 21:29:33

+0

至于你的ID - 创建你自己的一种方法分配MySQL以外的唯一引用。 – 2012-01-17 21:30:37

2

不知道有关细节MySQL,但是这意味着任何有自尊的RDBMS有所谓的“序列”实体用作适合表主键唯一值的来源。

下面是使用序列解决您的问题的方法,这是我多次遇到的问题。使用伪代码:

  1. 开始交易从某种序列
  2. 选择3个一个值。同样,任何自尊的RDBMS将保证每个“下一个序列值”的查询都会返回唯一值,适合用作主键。三个选定的值将用于locations,event_info,event_times中新记录的主键;
  3. 使用第1步的值执行INSERT INTO locations;
  4. 使用第1步的值执行INSERT INTO event_info;
  5. 使用第1步的值执行INSERT INTO event_times;
  6. COMMIT交易,如果一切顺利的话。否则,交易为ROLLBACK

在一次交易中使所有INSERT成为必需。 为了进一步增强,您可以批量查询。

UPDATE之前符合您的有关数据可能前生要求INSERT小号

如果您更新报文总是包含完整的一组数据:也就是位置,event_info和event_times:上方。然后使用方法并删除表中的旧记录。这假定您可以使用SELECT旧实例使用主键以外的一些数据(即数据称为域级主键)。不要忘记在同一个交易中制作DELETE

+0

我该如何处理刚才在EDIT中提到的问题,以解决我原来的问题? – hackartist 2012-01-17 21:16:41

+1

@hackartist更新了答案 – 2012-01-17 21:36:36

+0

谢谢,我投了你的答案。另一个答案在几分钟前提出,我使用REPLACE INTO,它会为我删除和插入,但如果他没有先回答我会接受你的答案。谢谢。 – hackartist 2012-01-17 21:40:14