承接国内外服务器租用托管、定制开发、网站代运营、网站seo优化托管接单、网站代更新,新老站点皆可!!咨询QQ:3787320601

10种Java开发者编写SQL语句经常见毛病

管理员 2023-07-05 09:29:12 互联网圈 12 ℃ 0 评论 9382字 收藏

Java开发者对面向对象编程思惟与命令行编程思惟的调和程度,取决于他们以下几种能力的水平:

技能(任何人都可以编写命令行情势的代码)
教条(有的人使用“模式 – 模式”的方式,即模式无处不在,并以名字作为标识)
情绪状态(在早期,真正面向对象情势的代码比起命令式代码会更加难懂。)

但是,当Java开发人员编写SQL语句时,一切都变得区别了。SQL是一种说明式语言,与面向对象思想和命令式思想无关。在SQL语言中,查询非常容易表达。但它也不是那末容易以最好或最正确地方式编写出来。开发人员不但需要重新思考自己的编程模式,还需要从集合论的角度进行深入思考。

以下是Java开发人员使JDBC或jOOQ编写SQL语句时,几种常见的毛病

1.忘记了NULL

误解NULL的含义多是Java开发人员编写SQL最常犯的毛病。这有多是由于NULL也被称为UNKNOWN,但也有其他的缘由。固然如果它只被叫做UNKNOWN,会更容易理解一些。另外一个缘由是,JDBC在获得数据,或绑定变量时,SQL中的NULL被映照到Java中的null。这可能会致使人们认为类似Java中null==null的情况,SQL中也存在NULL= NULL。

一个更离奇的误解NULL的例子是,当NULL谓词用于行值表达式时。

另外一个奥妙的问题产生与对NOTIn 反连接中NULL含义的误解。

解决办法

不断的训练自己。要时刻明确NULL的含义,每次你写SQL时,都要斟酌:

对NULL来讲谓词会不会正确?
NULL会不会影响该函数的结果?
2.在Java内存中处理数据

一些Java开发者十分了解SQL特性。偶尔JOIN,零散的UNION,没甚么问题。但如果遇到视窗功能,结果集分组等情况又怎样样呢?很多Java开发人员会把SQL数据加载到内存,把数据转换成一些合适的集合类型,以十分冗杂的循环结构在集合上履行恼人数学运算(最少在Java 8改进容器之前是这样的)。

但一些SQL数据库除支持SQL标准外,还支持先进的OLAP特性,履行效力更好,且更容易编写。一个非标准的例子就是甲骨文的MODEL子句。只是让数据库进行数据处理进程,将终究获得的结果加载到Java内存中。由于一些非常聪明的人已优化了这些昂贵的产品。所以,事实上,通过向OLAP数据库上进行迁移,您将得到两个好处:

简洁。它可能使得在SQL中编写正确代码会比在Java中相对容易
性能。该数据库将可能比你的算法要快。更重要的是,你没必要再通过网络传输数百万条记录。
解决办法

每次你在Java中实现以数据为中心的算法时,要试着问问自己:有无办法让数据库履行这些工作,而只把结果交付给我?

3.尽可能使用UNION,而不是UNION ALL

相对UNION,UNION ALL需要额外的关键字显得相形见绌。如果在SQL标准已定义以下支持,那将会好很多:

UNION(允许重复)
UNION DISTINCT(去掉重复)
一般很少需要去除重复(有时去重乃至是毛病的),而且对具有很多列的大结果集,它常常很慢,由于这两个子查询需要排序,每一个元组都需要与随后的元组进行比较。

需要注意的是,即便SQL标准指定了INTERSECTALL和EXCEPTALL,但几近没有任何数据库实现这些用途不大的操作。

解决办法

你每次写到UNION时,要斟酌下你会不会实际上想写的是UNIONALL。

4.使用JDBC分页功能将大量结果分页

大多数数据库都支持通过LIMIT.. OFFSET,TOP .. START AT、OFFSET.. FETCH等子句以某种方式对结果进行分页。在没有对这些子句的支持下,但依然有ROWNUM(Oracle)或ROW_NUMBER()OVER()(DB2,SQL Server 2008和更低版本),这比在内存中分页要快很多。而且这对大数据集更是明显。

解决办法

只要使用那些子句或工具(如jOOQ),可以为你摹拟上述分页子句。

5.将Java内存中实现连接

从SQL的发展的早期,一些开发商在面对SQL连接时依然有一种不安的感觉。一直存在着一种固有的恐惧—JOIN速度缓慢。如果基于本钱的优化器选择履行嵌套循环,创建一个连接表源之前,加载完全表到数据库内存,那速度确切十分缓慢。但很这少产生。通过适当的谓词,束缚和索引,MERGEJOIN和 HASHJOIN操作是非常快的。这与正确的元数据相关(我不用再举Tom Kyte的例子了)。但是,也有依然可能有很多Java开发人要会从单独的查询中加载两个表到map容器中,在java内存中以某种方式进行连接操作。

解决办法

如果你从多个步骤的多个表中进行了SELECT操作,那要慎重斟酌一下会不会可以在一条语句中表达你所需要的查询功能。
6.使用DISTINCT或UNION从一个笛卡尔积中删除重复

冗杂连接的存在,会致使SQL语句中起作用的关系显得十分疏松。具体地,如果触及到多列外键关系,很有可能忘记在JOINON子句上添加谓词。这可能会致使重复的记录,但或许只在特殊情况下。然后一些开发者可能会选择使用DISTINCT再次删除这些重复记录。这类毛病有三种危害:

可能治标不治本。乃至在某些边沿情况下,标都治不了
这在有很多列的大结果集上会十分的缓慢。DISTINCT会履行ORDER BY操作来删除重复。
这在大型笛卡尔积中也十分的缓慢,由于这样做依然会致使在内存中加载大量数据。
解决办法

作为一个经验法则,当你得到不想要的重复结果时,应当首先检查你的连接谓词。由于有多是在某个地方存在着一个不容易发觉的笛卡尔积。

7.不使用MERGE语句

严格意义上讲,这不是一个真实的毛病,可能只是对功能强大的MERGE语句缺少足够的认知或存在着某种恐惧而已。有些数据库包括其他情势的UPSERT 语句,如MySQL的ONDUPLICATE KEY UPDATE子句。但MERGE真的十分强大,最重要的是在数据库中,它在很大程度上扩大了SQL标准,如SQL Server。

解决办法

如果你通过链接INSERT和UPDATE或链接SELECT… FOR UPDATE来实现UPSERTING,那末你要多想想。抛开与运行条件的风险,你或许可使用一个简单的MERGE语句来到达目的。

8.使用了聚合函数,而不是窗体功能

引入窗函数之前,使用GROUPBY子句与投影聚合函数是汇总数据的唯一方式。这在大部份情况下都十分有效,如果聚集后的数据需要由常规的数据进行补充,该分组的查询可以置于连接子查询中。

但是,SQL:2003定义了窗口功能,目前很多主流的数据库厂商也纷纭实现了窗口功能。窗口功能可以聚集结果集中未被分组的数据。事实上,每一个窗口的功能支持本身独立的PARTITIONBY子句,这对报表类利用是一个非常有用的工具。

使用窗口功能将:

致使更多的可读性SQL(减少子查询中非专用GROUP BY子句的存在)
提高性能,作为一个RDBMS极可能更容易优化其窗口功能。
解决办法

当你在一个子查询写一个GROUPBY子句时,仔细想一想这会不会能用一个窗口函数来完成。

9.使用内存排序法进行间接排序

在SQLORDER BY子句支持多种类型的表达式,包括CASE语句,这对间接排序非常有用。你应当永久可能在Java内存中对数据进行排序,由于你认为:

SQL排序太慢
SQL排序不能做到这一点
解决办法

如果你在内存中对任何SQL数据进行排序,请仔细想一想,你会不会能把排序迁移至数据库中。这和将分页迁移至数据库中的缘由一样。

10 一个接一个的插入大量的记录

JDBC包括了批处理,而且你应当使用它。面对不计其数的记录,切勿为每条记录都创建一个新的PreparedStatement来进行插入操作。如果你要将所有记录都插入到同一个表,使用单一的SQL语句和多个绑定值集合建立一个批处理的INSERT语句。根据您的数据库和数据库配置,您可能需要在一定数量的插入的记录落后行提交,为了保持UNDO日志不过分庞大。

解决办法

始终批量插入大型数据集。

Java开发者编写SQL语句经常见的10种毛病,大家是不是是有了大概了解,希望在编写的进程中一定要特别注意!

文章来源:丸子建站

文章标题:10种Java开发者编写SQL语句经常见毛病

https://www.wanzijz.com/view/61843.html

X

截屏,微信识别二维码

微信号:weimawl

(点击微信号复制,添加好友)

打开微信