Featured article by oschina reproduced with permission by Data Geekery GmbH.
Java顺序员编程时需求混杂面向工具思想和普通号令式编程的办法,可否完满的将二者联合起来完整得依托编程职员的水准:
但当Java顺序员写SQL语句时,一切都纷歧样了。SQL是阐明性言语而非面向工具或是号令式编程言语。在SQL中要写个查询语句是很容易的。但在Java里相似的语句却不轻易,由于顺序员不只要重复思索编程范式,并且也要思索算法的问题。
下面是Java顺序员在写SQL经常犯的错误(没有特定的次序):
Java顺序员写SQL时对NULL的曲解多是最大的错误。或许是由于(并不是独一来由)NULL也称作UNKNOWN。假如被称作UNKNOWN,这还好了解些。另外一个缘由是,当你从数据库拿工具或是绑定变量时,JDBC将SQL NULL 和Java中的null对应了起来。如许招致了NULL = NULL(SQL)和null=null(Java)的曲解。
关于NULL最大的曲解是当NULL被用作行值表达式完好性束缚前提时。
另外一个曲解呈现在关于NULL 在 NOT IN anti-joins的使用中。
处理办法:
好好的练习你本人。当你写SQL时要不断得想到NULL的用法:
很少有Java开发者能将SQL了解的很好.偶然运用的JOIN,另有乖僻的UNION,好吧.可是关于窗口函数呢?另有对聚集实行分组呢?很多的Java开发者将SQL数据加载到内存中,将这些数据转换成某些附近的聚集类型,然后再那些聚集上面运用鸿沟轮回把持构造(最少在Java8的聚集晋级之前)履行使人生厌的数学运算.
可是一些SQL数据库支撑进步前辈的(并且是SQL规范支撑的!)OLAP特征,这一特征表示更好并且写起来也愈加便利.一个(其实不怎样规范的)例子就是Oracle超棒的MODEL分句.只让数据库来做处置然后只把后果带到Java内存中吧.由于究竟一切十分聪慧的家伙曾经对这些昂贵的产品实行了优化.因而实践上,经过将OLAP移到数据库,你将取得一下两项益处:
完美的办法:
每次你运用Java完成一个以数据为中间的算法时,问问本人:是否一种办法可让数据库替代为我做这类费事事.
太可耻了,和UNION比拟UNION ALL还需求额定的关键字。假如SQL规范曾经规则了支撑,那末可能会更好点。
移除反复行不只很少需求(有时乃至是错的),并且关于带非常多行的大数据聚集会相当慢,由于两个子select需求排序,并且每一个元组也需求和它的子序列元组比较。
留意即便SQL规范规则了INTERSECT ALL和EXCEPT ALL,很少量据库会完成这些没用的聚集操作符。
处置办法:
每次你写UNION语句时,思索实践上能否需求UNION ALL语句。
大部分的数据库都会支撑一些分页号令完成分页后果,比方LIMIT..OFFSET,TOP..START AT,OFFSET..FETCH语句等。即便没有支撑这些语句的数据库,仍有可能对ROWNUM(甲骨文)或许是ROW NUMBER() OVER()过滤(DB2,SQL Server2008等),这些比在内存中完成分页更疾速。在处置大量数据中,后果特别分明。
改正:
仅仅运用这些语句,那末一个Tools(例如JOOQ)就能够模仿这些语句的操作。
从SQL的早期Start,当在SQL中运用JOIN语句时,一些开发者依旧有不安的觉得。这是源自对参加JOIN后会变慢的固有胆怯。假设基于本钱的优化选择去完成嵌套轮回,在创立一张衔接表源前,可能加载一切的表在数据库内存中,这多是真的。可是这事发作的几率太低了。经过适宜的猜测,束缚和索引,兼并衔接和哈希衔接的操作都是相当的快。这完整是是关于准确元数据(在这里我不克不及够援用Tom Kyte的太多)。并且,可能依然有很多的Java开发职员加载两张表经过离开查询到一个映照中,而且在某种水平上把他们加到了内存傍边。
改正:
假设你在各个步调中有从各类表的查询操作,好好想一想能否可以表达你的查询操作在单条语句中。
经过庞杂的衔接,人们可能会对SQL语句中饰演关键脚色的一切关系失去观点。特殊的,假如这触及到多列外键关系的话,很有可能会遗忘在JOIN .. ON子句中增加相干的判别。这会招致反复的记载,但也许只是在特别的状况下。有点开发者因而可能选择DISTINCT来消弭这些反复记载。从三个方面来讲这是错误的:
处理办法:
依据经历,假如你取得了不需求的反复记载,仍是反省你的JOIN判别吧。可能在某个地方有一个很难察觉的笛卡尔积聚集。
其它翻译版本 (1) 加载中这并非一个过失,可是多是缺少常识或许关于强悍的MERGE语句决心缺乏。一些数据库了解其它方式的更新拔出(UPSERT)语句, 如 MYSQL的反复主键更新语句,可是MERGE在数据库中确是很弱小,很主要,以致于大举扩大SQL规范,例如SQL SERVER。
处理之道:
假如你运用像结合INSERT和UPDATE或许结合SELECT .. FOR UPDATE然后在INSERT或UPDATE等更新拔出时,请三思。你完整可使用一个更容易的MERGE语句来阔别冒险竞争前提。
其它翻译版本 (1) 加载中在引见窗口函数之前,在SQL中聚合数据意味着运用GROUP BY语句与聚合函数相映照。在非常多情况下都任务得很好,如聚合数据需求稀释惯例数据,那末就在join子查询中运用group查询。
可是在SQL:2003中定义了窗口函数,这个在非常多主流数据库都完成了它。窗口函数可以在后果集上聚合数据,可是却没有分组。现实上,每一个窗口函数都有本人的、自力的PARTITION BY语句,这个Tools关于显示陈述太TM好了。
运用窗口函数:
处理办法:
当你在子查询中运用GROUP BY语句时,请再三思索能否可使用窗口函数完成。
SQL的ORDER BY语句支撑非常多类型的表达式,包含CASE语句,关于直接排序非常有效。你可能重来不会在Java内存中排序数据,由于你会想:
处置办法:
假如你在内存中排序任何SQL数据,请再三思索,能否不克不及在数据库中排序。这关于数据库分页数据非常有效。
本文中的一切译文仅用于进修和交换目标,转载请务必注明文章译者、出处、和本文链接。 2KB翻译任务按照 CC 协议,假如我们的任务有进犯到您的权益,请实时联络我们。2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务