使用大型 mysql 数据库改进查询 UPDATE

Posted

技术标签:

【中文标题】使用大型 mysql 数据库改进查询 UPDATE【英文标题】:Improving a query UPDATE using large mysql databases 【发布时间】:2014-03-20 00:56:36 【问题描述】:

我正在尝试使用以下查询更新我相当强大的数据库(近 300 万行):

$length = strlen($this);

$query = "UPDATE database 
SET row_to_update='1' 
WHERE row='$this' 
AND row_length='$length' 
LIMIT 1";

它从一个文件(很多)中获取单词($this),然后搜索匹配。如果找到,它会将 row_to_update 更新为值 1(将 none 设置为默认值)。

每个 row_length 已经包含某个单元格的长度值,我认为这可能会显着加快处理速度。可惜没有。

它在 8 小时内仅管理约 30k 个查询。至少可以这么说,这很慢!

有什么办法,我可以改进这个低效的代码吗?

【问题讨论】:

您是否按行运行此查询? 获得了您在where 子句中使用的所有字段的索引?再加上为什么要存储 row_Length 字段?在查询中执行length(somefield) 很简单,因为数据库已经“知道”字段内容的长度。 虽然你可以连接$this,这样你就可以对一堆记录运行一次查询吗?例如WHERE row IN ($this_concatinated) AND row_length IN ($length_concatincated) @MarcB 我铭记在心,推荐它(row_length),记住 Mark Byers 对我的问题link 最后列出的 cmets 之一 @MarcB 还没有索引。需要在该主题上做我的功课(从未做过)。这没什么好骄傲的,但至少我承认了。 【参考方案1】:

尝试收集一堆你正在寻找和使用的值

UPDATE table SET row_to_update='1' WHERE row IN ($my_values);

您可以使用EXPLAIN <your_query>EXPLAIN EXTENDED .. 来检查它是否使用索引并调整查询或创建索引以加快速度。以这种方式在相同的WHERE 条件下使用SELECT

您可以使用更多:

SET profiling = 1;
<your query goes here>
SHOW PROFILES;
SHOW PROFILE FOR QUERY 1;

如果它不在开发中,请小心。环境。

考虑用您感兴趣的值填充临时表并以这种方式使用它:

UPDATE table SET row_to_update='1' WHERE row in (SELECT values FROM my_temp_table);

当你到达那里时,你可以改进它:

UPDATE table INNER JOIN temp_table ON table.row = temp_table.row SET row_to_update = '1';

示例:

正如您所要求的示例。说example 表代表你原来的表,里面有很多数据。在本例中,我将只使用 4 行:

mysql> select * from example;
+----+------+
| id | data |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | d    |
+----+------+
4 rows in set (0.00 sec)

假设您正在寻找具有 data= 'a'、'b' 或 'c' 的行的 ID 您可以通过 3 种方式做到这一点:

1) SELECT ... IN(列表)

mysql> select id from example where data in ('a', 'b', 'c');
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
+----+
3 rows in set (0.00 sec)

2) SELECT ... IN (SELECT ... FROM temp_table)

mysql> select * from temp_table;
+----+------+
| id | data |
+----+------+
| 10 | foo~ |
| 11 | a    |
| 12 | bar  |
| 13 | baz  |
| 14 | b    |
| 15 | c    |
+----+------+
6 rows in set (0.00 sec)

mysql> select id from example where data in (SELECT data from temp_table);
[..]
3 rows in set (0.00 sec)

3) SELECT ... INNER JOIN temp_table ...

mysql> select example.id from example inner join temp_table on example.data = temp_table.data;
[..]
3 rows in set (0.01 sec)

当您准备好时,使用具有相同条件的 UPDATE 来应用您喜欢的更改。

【讨论】:

有没有机会我可以问你一个如何使用IN子句的例子,好吗?做了一些研究,但还没有运气。它是仅从不同的表中获取值,还是我也可以像 $this 那样解析 .php $values? 更新表 SET row_to_update='1' WHERE row IN (SELECT row FROM database where row='$this');不会工作 我刚刚用一个例子编辑了我的答案.. 给我一分钟,我也会给你一个嵌套 SELECT 的.. "UPDATE wyrazy SET row_to_update='1' WHERE wyraz IN (select wyraz_id from wyrazy where wyraz in ('$word_from_list'))";也不行。 所以首先创建 temp_table 并用许多 INSERT 填充它,尽可能多地读取您的文件。运行 INNER JOIN,你会得到结果。如果 TEMPORARY TABLE 不足以存储数据,你也可以使用普通 TABLE。如果您对这些 INSERT 只有一个进程,而不是使用 MyISAM 引擎而不是 InnoDB。在这种情况下会表现得更好。

以上是关于使用大型 mysql 数据库改进查询 UPDATE的主要内容,如果未能解决你的问题,请参考以下文章

mysql UPDATE 语句 - 相同值的开销?

如何使用 AES_ENCRYPT 和 PDO 准备语句改进大型加密数据库的 PHP 解决方法?

使用子查询改进 MySql 查询左外连接

MySQL UPDATE 查询

如何改进这个 mysql 数据透视查询?

雷林鹏分享:MySQL UPDATE 查询