【发布时间】:2015-10-05 00:50:45
【问题描述】:
我有一个非常复杂的 sql 查询 - 逻辑很简单,但我需要连接 17 个表(每个表有 10-20 个字段和 100 到 100 万条记录),所以有很多(LEFT)JOIN 和 WHERE条款。
SELECT table1.column_A
table2.column_B
table3.column_C
table4.column_D
....
FROM table1
LEFT JOIN table2 ON table1.column_a = table2.column_b
JOIN table3 ON table3.column_c = table1.column_d
LEFT JOIN table4.column_e = table3.column_f
AND LENGTH(table4.column_g) > 6 AND (table4.column_h IN (123,234))
LEFT JOIN ....
....
WHERE table1.column_i = 21
AND (table1.column_j IS NULL OR DATE(table1.column_k) <> DATE(table1.column_l))
上面的查询只需要 5 秒就可以在 MySQL 中运行。但是当我在 sqlite in-memory db 中运行它(在 Linux 上使用 Perl)时,大约需要 20 分钟。这还是可以接受的。
当我添加一个 ORDER BY 子句(我确实需要这个)时,执行时间会急剧增加。
ORDER BY table1.column_m, table6.column_n, table7.column_o IS NULL;
在 MySQL 中需要 40 秒。在 sqlite in-memory db 中(在 Linux 上使用 Perl),我等了一个多小时,但仍然没有完成。
我需要做什么样的调整来加快查询速度?我的阈值在 1 小时内。
我将其设为内存数据库的原因是我收到了 SQL 生成的规范化数据,但我们最终需要将数据加载到非 SQL 数据库中,所以我不想创建中间 SQL db 仅用于数据加载 - 这使代码变得丑陋并增加了维护复杂性。另外,我目前面临的时间问题只是一次性的。未来我们每天收到的数据量会小很多(不到我今天的1%)
提前感谢您的帮助!!
【问题讨论】:
-
如果不查看表结构和正在运行的确切查询,可能很难解决性能问题。由于您正在使用大量表,因此我建议您只使用几个测试表创建一个类似查询的minimal, complete, verifiable example。然后您可以显示您在 MySQL 和 SQLite 中使用的表定义,以及每个表的时间。
-
MySQL 表是在内存中(
ENGINE = MEMORY)还是标准表?不要忘记在 Perl 中对结果进行排序可能会更快 -
MySQL 表是标准表(在 Windows 上),而 sqlite 在 Linux 上是内存表。
-
数据库可能在内存中,但这并不意味着磁盘没有发挥作用,尤其是当您加入大量大型表时。购买足够大的 SSD 并升级内存。
标签: mysql database perl sqlite in-memory-database