使用大型 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的主要内容,如果未能解决你的问题,请参考以下文章