【问题标题】:mysql query optimization problemmysql查询优化问题
【发布时间】:2011-05-07 00:51:34
【问题描述】:

我正在尝试从大型数据库中导入数据。我有两张表,有几十万条记录。我必须在两个表中搜索数据,然后将该记录插入到一​​个新表(第三个表)中,如果该记录已经存在于第三个表中,那么我必须更新第三个表中的一个列记录。

这听起来很容易,但处理起来需要很长时间。

以下是示例查询和伪代码:

select * from table1 INNER JOIN table2 USING(id)

search in table 3 -> 
 if record exist{
  update record in table 3 (update counter in a column)
 }else{
  Insert new record in table 3
 }

第一张和第二张表有超过二十万条记录。当我开始在第三张表中插入记录时,它会降低整个速度,因为它还必须在第三张表中搜索以更新或插入记录。

Database Name = MySql
Language = Php

有什么问题?我该如何改进呢?我不能等待几个小时来处理它:(

谢谢

编辑:

表3中,id有主键,其他列正常。数据库模式太大而且复杂。你们要吗,我这里贴上百行?

请大家指出我的伪代码和查询中的错误吗?我可以使用什么索引或结构来提高性能?

结构

Table 1 - usr_id, first name, last name (usr_id is primary key)
Table 2 - id, usr_id, amount (id is primary key and usr_id is foreign key)

Table 3 - new_id , first name, last name, usr_id, total_amount (new_id is primary key and usr_id is foreign key

)

我检查表 3 的名字和姓氏是否相同,然后更新总金额,如果它们不同,则插入一条新记录

【问题讨论】:

  • 您能发布您的数据库架构吗?听起来 table3 的索引不正确。
  • 您必须向我们展示更多有关您的表结构和索引的信息。

标签: php mysql sql


【解决方案1】:

从您的伪代码中,我看到您检查了表 3 中 select * from table1 INNER JOIN table2 USING(id) 中每条记录的记录是否存在。您最终会得到数千个降低性能的select 命令。您可以通过

来改进它
select t1.*, t2.*, t3.pk_field from table1 t1 INNER JOIN table2 t2 USING(id)
LEFT JOIN table3 t3 ON (join codition)

现在您可以测试t3.pk_field 是否为空(如果为空则插入,否则更新)。改进它的下一步是编写一个处理所有事情的查询,使用 jasonbar 提出的INSERT ON DUPLICATE KEY UPDATE

INSERT INTO table3(col1, col2,...) 
 select t1.col1, t1.col2, t2.col3, .... 
 from table1 t1 INNER JOIN table2 t2 USING(id)
ON DUPLICATE KEY UPDATE counter = new_value

【讨论】:

  • 谢谢,对于表 3,我检查了名字和姓氏是否相同,然后更新当前余额的值(使用一些预定义的公式)。当您说 t3.pk_field 时,我无法理解,因为我的名字、姓氏和余额列是普通列,不是主键或外键。
  • 我使用t3.pk_field 只是为了举例(我不知道你的表结构)。可以是Table3中任何不能正常为null的字段(null值表示表中不存在记录,需要插入记录而不是更新)
  • 我更新了我的问题并尝试使用最简单的表格版本来解释我的问题。
  • DUPLICATE KEY UPDATE 不起作用,因为我的列没有任何检查重复项的键:( 还有其他解决方案吗?
  • 为什么要在 Table3 中存储名字/姓氏和 usr_id ?如果 Table3 引用了 Table1.usr_id,则只有 usr_id 应该在 Table3 中。如果您尝试创建一个新的用户表,您应该只在 Table3 中存储名字/姓氏。此外,在 (table3.first_name,table3.last_name) 上添加 [unique?] 索引将显着提高性能。
【解决方案2】:

您应该查看INSERT ON DUPLICATE KEY UPDATE 语法。

类似:

INSERT INTO `table3` (`col1`, `col2`) VALUES('val1', 'val2')
ON DUPLICATE KEY UPDATE `counter` = `counter` + 1;

如果一个简单的选择查询来查看 table3 中是否已经存在该行花费的时间太长,那么您可能没有使用索引(或者至少没有正确使用它们)。我们需要更多信息来尝试解决问题。

【讨论】:

  • 能否请您指出为什么它需要太长时间?什么是提高性能的好结构?
  • 我正在更新的列不是唯一的,也不是主键。您提出的查询需要上述任何条件。让我更新我的问题以提供更多信息:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 2011-07-07
  • 2018-12-21
相关资源
最近更新 更多