【发布时间】:2021-09-02 10:53:30
【问题描述】:
我在一张桌子上使用 CakePHP 的 Tree behavior 来映射一个文件系统结构。 实际文件保存在与 Amazon S3 兼容的系统上,SQL 表模仿文件夹结构,文件键中的每个“文件夹”对应一行。 随着时间的推移,这个表已经增长到包含 700K+ 行。 当尝试添加一个新文件夹或删除一个空文件夹时,会执行两个类似这样的查询:
UPDATE sys_files SET lft = ((lft - 2)) WHERE (lft > 2443)
UPDATE sys_files SET rght = ((rght - 2)) WHERE (rght > 2443)
每一个都需要 30 多秒的时间来运行,这给用户带来了非常不愉快的体验,用户需要等待操作完成一分钟或更长时间。有时,HTTP 调用只是超时,这更糟。
发生这种情况是因为这些查询几乎更新了(非常大的)表中的每一行,如这些结果所示。
mysql> SELECT COUNT(*) FROM sys_files;
+----------+
| COUNT(*) |
+----------+
| 713259 |
+----------+
1 row in set (0.09 sec)
mysql> SELECT COUNT(*) FROM sys_files WHERE lft > 2443;
+----------+
| COUNT(*) |
+----------+
| 704520 |
+----------+
1 row in set (0.11 sec)
mysql> SELECT COUNT(*) FROM sys_files WHERE rght > 2443;
+----------+
| COUNT(*) |
+----------+
| 704546 |
+----------+
1 row in set (0.11 sec)
我尝试在 lft 和 rght 字段上添加索引,但这并没有帮助,因为缓慢的部分是 700K+ 行的实际更新,没有更新查询的 WHERE 条件。而且,添加索引并没有使性能明显变差,所以我并不担心保留或离开它......问题在于更新本身,无论有没有索引。
【问题讨论】:
-
“左右”设计很可爱,但效率不高。
-
特别是,
UPDATEing700K 行的 any 表会很慢。由于需要更新索引和数据,添加索引会使其变慢。
标签: php mysql cakephp tree cakephp-3.0