使用 SQL 和 Java 程序提高性能

Posted

技术标签:

【中文标题】使用 SQL 和 Java 程序提高性能【英文标题】:Better Performance with SQL and Java Program 【发布时间】:2018-12-22 18:31:57 【问题描述】:

我有一个代码,我从各种来源获取数据,并对它们进行排序和排序以发送给用户。

我通过触发一个包含多个连接到 DTO 列表的查询来获取数据,然后我再次触发另一个查询,该查询进一步包含多个连接到同一个 DTO 列表。然后我添加要呈现给用户的两个 DTO 列表。

查询 1: 从 TABLE1、TABLE2 中选择 *....

查询 2: 从 TABLE5、TABLE7 中选择 *....

dto1.addAll(dto2);

dto1.sort(Comparator....);

我以编程方式再次对其进行排序是因为以下原因:

Query 1 returned sorted data lets assume
1,2,3,4
Query 2 returned sorted data lets assume
1,2,3,4

After combining both the lists, I will get
1,2,3,4,1,2,3,4
Expected data
1,1,2,2,3,3,4,4

我的问题是,在哪种情况下性能会更好?

    从两个查询中获取排序后的数据,添加列表,然后对它们进行排序和排序。 从两个查询中获取未排序的数据,添加列表,然后只排序一次。

在第一种情况下,它会被排序三次,但在第二种情况下,它只会排序和排序一次。

当我将数十万条记录放入表中进行测试时,我没有发现太大差异,第二种情况比第一种情况要快一些。

那么,在效率和性能方面,应该推荐哪一个呢?

【问题讨论】:

如果查询只针对一个数据库,则将查询变为一个并让 DBMS 进行排序。否则,您可以让它排序并稍后合并/排序两个结果,这应该非常有效。至少在理论上。但我不知道您使用的对象是否以及如何支持这种方法。 那么,在效率和性能方面,应该推荐哪一个? 执行有效基准测试时表现出更好性能的那个。真正的优化将涉及为您当前正在做的事情寻找算法上更好的解决方案。显然,一次排序应该比三次排序快 3 倍;但是您还没有真正证明这就是您的代码在这两种情况下的作用(如果您正在获取已排序的数据,为什么然后您需要再次“排序和排序”?它已经排序了)。 .. FROM TABLE1, TABLE2?不要使用逗号语法来连接表。上世纪末已经过时了。请改用JOIN 语法。 @stickybit,正如我所提到的,我无法合并查询。此外,如果我对查询进行排序,那么在合并后,我将不得不再次对其进行排序以获得最终的 DTO。 您的 merge 已损坏。你已经知道这两个列表是排序的,合并两个排序的列表可以在线性时间内产生一个排序的输出。 【参考方案1】:

全部在 mysql 中完成:

( SELECT ... )
UNION ALL
( SELECT ... )
ORDER BY ...

不用担心在两个选择中排序;等到最后再做吧。

ALL 假设没有你需要摆脱的重复。

这种方法可能最快,因为它是对数据库的单个 SQL 请求。而且因为它只做一种。

【讨论】:

您的解决方案非常简洁。我从来没有真正考虑过,但ORDER BY 是否适用于组合结果集? @TheImpaler - 是的。这个“功能”至少从 4.0 版开始就存在了。 @TheImpaler - 在旧版本中,省略括号会使ORDER BY 是属于最后一个SELECT 还是属于UNION 产生歧义。我用括号来说明清楚。 这个解决方案有效,但正如我已经提到的,我不能同时加入这两个查询,因为它会在代码中产生紧密耦合。我将不得不单独获取数据【参考方案2】:

我认为这三个都会有相似的表现。您可以使用其中一种获得更高的速度,但我认为这不会很重要。

现在,就负载而言,情况就不同了。您是否更受 CPU 资源(在本地机器中)或数据库资源(在远程数据库服务器中)的限制?大多数情况下,当您的应用程序将处理许多其他内容时,数据库将处于空闲状态。如果是这种情况,我宁愿将负载放在数据库上,而不是应用程序本身:也就是说,我会让数据库在一个单个 SQL 调用中组合和排序数据;那么应用程序将简单地使用现成的数据。

2018 年 12 月 22 日编辑:

如果两个查询都在同一个数据库上运行,您可以将它们作为一个单独的查询运行,并使用 CTE(通用表表达式)组合结果。例如:

with
x (col1, col2, col3, col4, ...) as (
  select * from TABLE1, TABLE2... -- query 1
  union all
  select * from TABLE5, TABLE7... -- query 2
)
select * from x
order by col1

最后的ORDER BY 对组合结果进行操作。或者,如果您的数据库不支持 CTE,您可以编写:

select * from (
  select * from TABLE1, TABLE2... -- query 1
  union all
  select * from TABLE5, TABLE7... -- query 2
) x
order by col1

【讨论】:

感谢您的回复,我无法将查询合并为一个,如果可能的话,我只会选择那个。我必须进行两个不同的数据库调用。正如我所说,如果我对查询进行排序,我仍然需要在程序中进行排序,因为两个排序后的查询将包含它们自己的数据,所以当我们合并它们时,我们仍然需要对它们进行排序。 有什么理由使用WITH 及其包袱,而不是在一个声明中完成所有操作? 如果两个查询在同一个数据库上运行,您可以将它们组合成一个。查看我的编辑。 @TheImpaler - 仍然矫枉过正;看我的答案。【参考方案3】:

我认为第二个表现更好,因为如果您在合并两个列表后运行排序算法。所以你不需要对 db 运行排序查询。因此,数据库排序查询成本不需要您的第二次查询。

但是,如果您按排序顺序检索数据,然后再次运行排序算法,则执行起来必须花费更多成本,尽管它可以忽略不计。

【讨论】:

以上是关于使用 SQL 和 Java 程序提高性能的主要内容,如果未能解决你的问题,请参考以下文章

The WAY to 优化JAVA程序设计和编码,提高JAVA性能

如何提高子查询的性能或 sql 中子查询的替代方案

提高 mariaDB 查询的 sql 代码性能

优化设计提高sql类数据库的性能

在 Windows Phone 上使用 Linq to SQL 时,是不是可以提高批量删除的性能?

一些微小提高sql性能的方法