Java 程式員容易犯的10個SQL錯誤

来源:http://www.cnblogs.com/toyz/archive/2017/01/21/6337548.html
-Advertisement-
Play Games

Java程式員編程時需要混合面向對象思維和一般命令式編程的方法,能否完美的將兩者結合起來完全得依靠編程人員的水準: 技能(任何人都能容易學會命令式編程) 模式(有些人用“模式-模式”,舉個例子,模式可以應用到任何地方,而且都可以歸為某一類模式) 心境(首先,要寫個好的面向對象程式是比命令式程式難的多 ...


Java程式員編程時需要混合面向對象思維和一般命令式編程的方法,能否完美的將兩者結合起來完全得依靠編程人員的水準:

  • 技能(任何人都能容易學會命令式編程)
  • 模式(有些人用“模式-模式”,舉個例子,模式可以應用到任何地方,而且都可以歸為某一類模式)
  • 心境(首先,要寫個好的面向對象程式是比命令式程式難的多,你得花費一些功夫)

但當Java程式員寫SQL語句時,一切都不一樣了。SQL是說明性語言而非面向對象或是命令式編程語言。在SQL中要寫個查詢語句是很簡單的。但在Java里類似的語句卻不容易,因為程式員不僅要反覆考慮編程範式,而且也要考慮演算法的問題。

下麵是Java程式員在寫SQL時常犯的錯誤(沒有特定的順序):

 

1.忘掉NULL

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的用法:

  • 這個NULL完整性約束條件是正確的?
  • NULL是否影響到結果?
 

2.在Java記憶體中處理數據

很少有Java開發者能將SQL理解的很好.偶爾使用的JOIN,還有古怪的UNION,好吧.但是對於視窗函數呢?還有對集合進行分組呢?許多的Java開發者將SQL數據載入到記憶體中,將這些數據轉換成某些相近的集合類型,然後再那些集合上面使用邊界迴圈控制結構(至少在Java8的集合升級以前)執行令人生厭的數學運算.

但是一些SQL資料庫支持先進的(而且是SQL標準支持的!)OLAP特性,這一特性表現更好而且寫起來也更加方便.一個(並不怎麼標準的)例子就是Oracle超棒的MODEL分句.只讓資料庫來做處理然後只把結果帶到Java記憶體中吧.因為畢竟所有非常聰明的家伙已經對這些昂貴的產品進行了優化.因此實際上,通過將OLAP移到資料庫,你將獲得一下兩項好處:

  • 便利性.這比在Java中編寫正確的SQL可能更加的容易.
  • 性能表現.資料庫應該比你的演算法處理起來更加快.而且更加重要的是,你不必再去傳遞數百萬條記錄了.

完善的方法:

每次你使用Java實現一個以數據為中心的演算法時,問問自己:有沒有一種方法可以讓資料庫代替為我做這種麻煩事.

 

3. 使用UNION代替UNION ALL

太可恥了,和UNION相比UNION ALL還需要額外的關鍵字。如果SQL標準已經規定了支持,那麼可能會更好點。

  • UNION(允許重覆)
  • UNION DISTINCT (去除了重覆)

移除重覆行不僅很少需要(有時甚至是錯的),而且對於帶很多行的大數據集合會相當慢,因為兩個子select需要排序,而且每個元組也需要和它的子序列元組比較。

註意即使SQL標準規定了INTERSECT ALL和EXCEPT ALL,很少資料庫會實現這些沒用的集合操作符。

處理方法:
每次你寫UNION語句時,考慮實際上是否需要UNION ALL語句。

 

4.通過JDBC分頁技術給大量的結果進行分頁操作

大部分的資料庫都會支持一些分頁命令實現分頁效果,譬如LIMIT..OFFSET,TOP..START AT,OFFSET..FETCH語句等。即使沒有支持這些語句的資料庫,仍有可能對ROWNUM(甲骨文)或者是ROW NUMBER() OVER()過濾(DB2,SQL Server2008等),這些比在記憶體中實現分頁更快速。在處理大量數據中,效果尤其明顯。

糾正:

 

僅僅使用這些語句,那麼一個工具(例如JOOQ)就可以模擬這些語句的操作。

 

5.在java記憶體中加入數據

從SQL的初期開始,當在SQL中使用JOIN語句時,一些開發者仍舊有不安的感覺。這是源自對加入JOIN後會變慢的固有恐懼。假如基於成本的優化選擇去實現嵌套迴圈,在創建一張連接表源前,可能載入所有的表在資料庫記憶體中,這可能是真的。但是這事發生的概率太低了。通過合適的預測,約束和索引,合併連接和哈希連接的操作都是相當的快。這完全是是關於正確元數據(在這裡我不能夠引用Tom Kyte的太多)。而且,可能仍然有不少的Java開發人員載入兩張表通過分開查詢到一個映射中,並且在某種程度上把他們加到了記憶體當中。

糾正:

假如你在各個步驟中有從各種表的查詢操作,好好想想是否可以表達你的查詢操作在單條語句中。

 

6.在一個臨時的笛卡爾積集合中使用 DISTINCT 或 UNION 消除重覆項

通過複雜的連接,人們可能會對SQL語句中扮演關鍵角色的所有關係失去概念。特別的,如果這涉及到多列外鍵關係的話,很有可能會忘記在JOIN .. ON子句中增加相關的判斷。這會導致重覆的記錄,但或許只是在特殊的情況下。有些開發者因此可能選擇DISTINCT來消除這些重覆記錄。從三個方面來說這是錯誤的:

  • 它(也許)解決了錶面癥狀但並沒有解決問題。它也有可能無法解決極端情況下的癥狀。
  • 對具有很多列的龐大的結果集合來說它很慢。DISTINCT要執行ORDER BY操作來消除重覆。
  • 對龐大的笛卡爾積集合來說它很慢,還是需要載入很多的數據到記憶體中。

解決方法:

根據經驗,如果你獲得了不需要的重覆記錄,還是檢查你的JOIN判斷吧。可能在某個地方有一個很難覺察的笛卡爾積集合。

 

7. 不使用MERGE語句

這並不是一個過失,但是可能是缺少知識或者對於強悍的MERGE語句信心不足。一些資料庫理解其它形式的更新插入(UPSERT)語句, 如 MYSQL的重覆主鍵更新語句,但是MERGE在資料庫中確是很強大,很重要,以至於大肆擴展SQL標準,例如SQL SERVER。

解決之道:

如果你使用像聯合INSERT和UPDATE或者聯合SELECT .. FOR UPDATE然後在INSERT或UPDATE等更新插入時,請三思。你完全可以使用一個更簡單的MERGE語句來遠離冒險競爭條件。

 

8. 使用聚合函數代替視窗函數(window functions)

在介紹視窗函數之前,在SQL中聚合數據意味著使用GROUP BY語句與聚合函數相映射。在很多情形下都工作得很好,如聚合數據需要濃縮常規數據,那麼就在join子查詢中使用group查詢。

但是在SQL:2003中定義了視窗函數,這個在很多主流資料庫都實現了它。視窗函數能夠在結果集上聚合數據,但是卻沒有分組。事實上,每個視窗函數都有自己的、獨立的PARTITION BY語句,這個工具對於顯示報告太TM好了。

使用視窗函數:

  • 使SQL更易讀(但在子查詢中沒有GROUP BY語句專業)
  • 提升性能,像關係資料庫管理系統能夠更容易優化視窗函數

解決方法:

 

當你在子查詢中使用GROUP BY語句時,請再三考慮是否可以使用視窗函數完成。

 

9. 使用記憶體間接排序

SQL的ORDER BY語句支持很多類型的表達式,包括CASE語句,對於間接排序十分有用。你可能重來不會在Java記憶體中排序數據,因為你會想:

  • SQL排序很慢
  • SQL排序辦不到

處理方法:

 

如果你在記憶體中排序任何SQL數據,請再三考慮,是否不能在資料庫中排序。這對於資料庫分頁數據十分有用。

 

10. 一條一條的插入大量紀錄

JDBC ”懂“批處理(batch),你應該不會忘了它。不要使用INSERT語句來一條一條的出入成千上萬的記錄,(因為)每次都會創建一個新的PreparedStatement對象。如果你的所有記錄都插入到同一個表時,那麼就創建一個帶有一條SQL語句以及附帶很多值集合的插入批處理語句。你可能需要在達到一定量的插入記錄後才提交來保證UNDO日誌瘦小,這依賴於你的資料庫和資料庫設置。

關註流行國外網站

facebook:http://www.fb-on.com

facebook官網:http://www.facebookzh.com

facebook:http://www.cn-face-book.com

youtube:http://www.youtubezh.com

twitter:http://www.twitterzh.com

 

處理方法:
總是使用批處理插入大量數據。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Mac系統上雖然自帶PHP和Apache,但是有時不是我們想要的版本呢。今天我們就在macOS Sierra(10.12.1)上安裝比較新的版本的PHP版本,也就是PHP7.0+了。本篇博客我們安裝的Apache是2.4的版本, MySQL5.7.16。稍後會詳細介紹這一過程。 一、安裝前的準備 1 ...
  • 題目描述 一條消息被編碼為一個文本流,被逐字元地讀取。這個流包含了一系列由逗號分隔的整數,每個整數都可以用C的int類型表示。但是,一個特定整數所表示的字元取決於當前的解碼模式。共有3種這樣的模式:大寫字母、小寫字母和標點符號。 在大寫字母模式下,每個整數表示一個大寫字母:這個整數除以27的餘數表示 ...
  • Q:Access denied for user 'root'@'localhost' 錯誤 A:第一種:配置文件中把資料庫的用戶名密碼再改一遍,把runtime里的文件刪除 第二種:修改system的host文件,關聯 127.0.0.1 localhost ...
  • 我們到底能走多遠系列47 扯淡: 又是一年新年時,不知道上一年你付出了多少,收穫了多少呢?也許你正想著老闆會發多少獎金,也許你正想著明年去哪家公司投靠。 這個時間點好好整理一下,思考總結一下,的確是個非常好的機會。 年終的時候各個公司總會評一下績效,拉出各位的成績單,你是不是想說:去你媽的成績單,我 ...
  • Java,C#已經比較熟悉,最近在從0開始自學C++。學習過程中必然會與Java,C#進行對比,有吐槽,也有點贊。 先來講講最基本也是最重要的部分:參數傳遞的方式。 對於類型, Java分基本類型、複合類型,從另外一個角度分是值類型,引用類型。在展開對比前, 我們先來看看三個關鍵方式: 值 創建新的 ...
  • JDK、JRE、JVM JDK包含JRE,而JRE包含JVM JDK(Java Development Kit)是針對Java開發員的產品,是整個Java的核心,包括了Java運行環境JRE、Java工具和Java基礎類庫。Java Runtime Environment(JRE)是運行JAVA程式 ...
  • 我安裝的是Myeclipse 10.7.1。裝上好久沒用,今天啟動突然報錯:Failed to create the Java Virtual Machine。 檢查Myeclipse安裝好使用時好的啊,近期也沒用,可能是近期升級了本地單獨安裝的jre版本導致的吧(Myeclipse使用自己的jre... ...
  • 歡迎任何形式的轉載,但請務必註明出處。 1.jdk安裝及環境配置 點擊進入教程 2.Eclipse安裝 點擊進入官網下載 註意下載完成打開.exe後,出現的界面,有很多版本供選擇。選擇下圖版本 3.Tomcat安裝及環境配置 點擊進入教程 4.配置Tomcat伺服器 註意我下載的是V9.0版本,根據 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...