2ha*_*med 15 mysql performance join scalability query-performance
在某些情况下,需要非常大的查询将多个表与其中的子选择语句连接在一起以产生所需的结果。
我的问题是,我们是否应该考虑使用多个较小的查询,并通过多次调用查询数据库将逻辑操作带入应用程序层,还是最好一次性完成所有操作?
例如,考虑以下查询:
SELECT *
FROM `users`
WHERE `user_id` IN (SELECT f2.`friend_user_id`
FROM `friends` AS f1
INNER JOIN `friends` AS f2
ON f1.`friend_user_id` = f2.`user_id`
WHERE f2.`is_page` = 0
AND f1.`user_id` = "%1$d"
AND f2.`friend_user_id` != "%1$d"
AND f2.`friend_user_id` NOT IN (SELECT `friend_user_id`
FROM `friends`
WHERE `user_id` = "%1$d"))
AND `user_id` NOT IN (SELECT `user_id`
FROM `friend_requests`
WHERE `friend_user_id` = "%1$d")
AND `user_image` IS NOT NULL
ORDER BY RAND()
LIMIT %2$d
Run Code Online (Sandbox Code Playgroud)
最好的方法是什么?
Chr*_*ers 17
我将不同意这里使用 datagod 进行的大型复杂查询。我认为这些只有在它们杂乱无章的情况下才会出现问题。在性能方面,这些几乎总是更好,因为规划人员在如何检索信息方面有更多的自由。但是,编写大型查询时确实需要考虑可维护性。总的来说,我发现即使单个查询超过 200 行,简单、结构良好的 SQL 也很容易调试。这是因为通常您非常清楚您正在处理的问题类型,因此您只需检查查询中的几个区域。
当 SQL 的结构出现故障时,维护问题 IME 就会出现。子选择中长而复杂的查询会降低可读性和故障排除,内联视图也是如此,在长查询中应该避免这两种情况。相反,如果可以,请使用 VIEWs(请注意,如果您使用的是 MySQL,则视图的性能并不是那么好,但在大多数其他数据库上它们可以),并在那些不起作用的地方使用公共表表达式(MySQL 不支持这些)顺便提一句)。
从可维护性和性能情况来看,长时间的复杂查询都可以很好地工作,在这种情况下,您可以保持 where 子句简单,并且可以尽可能多地使用连接而不是子选择。目标是使“记录不显示”为您提供查询中的一些非常具体的位置来检查(它是在连接中删除还是在 where 子句中过滤掉?),因此维护团队其实可以维护东西。
关于可扩展性,请记住,规划器具有更大的灵活性,这也是一件好事......
编辑:你提到这是 MySQL,所以视图不太可能表现得那么好,而且 CTE 是不可能的。此外,给出的示例不是特别长或复杂,所以没问题。
dat*_*god 10
作为必须支持/清理这些庞大而复杂的查询的人,我会说将它们分解成几个易于理解的小块要好得多。从性能的角度来看,它不一定更好,但您至少为 SQL 提供了一个更好的机会来提出一个好的查询计划。
让跟随你的人的生活更轻松,他们会说你的好话。对他们施加压力,他们会诅咒你。
我对 2 个关键字查询性能和可伸缩性的 2 美分:
查询性能: SQL Server 并行已经很好地将查询分解为多线程搜索,所以我不确定通过为 SQL Server 执行它,您会看到多少查询性能改进。您将不得不查看执行计划以了解执行它时获得的并行度有多少,并比较两种方式的结果。如果您最终不得不使用查询提示来获得相同或更好的性能,那么 IMO 不值得这样做,因为稍后查询提示可能不是最佳的。
可扩展性: 正如 datagod 所说,读取查询可能更容易,如果您也可以在其他领域使用新查询,则将其分解为单独的查询是有意义的,但如果您不打算将它们也用于其他调用,那么管理 1 个任务将需要更多的存储过程,而 IMO 不会对可扩展性做出任何贡献。