如何用jdk8實作一個小型的關聯式資料庫系統

35
如何用JDK8實作一個小型的關聯式 資料庫系統 Kishida Naoki 2014-8-1 Taipei Java Developer Day

Upload: -

Post on 27-Aug-2014

4.925 views

Category:

Software


17 download

DESCRIPTION

Java Developer Day Taipei 2014

TRANSCRIPT

Page 1: 如何用JDK8實作一個小型的關聯式資料庫系統

如何用JDK8實作一個小型的關聯式資料庫系統

Kishida Naoki

2014-8-1 Taipei Java Developer Day

Page 2: 如何用JDK8實作一個小型的關聯式資料庫系統

自己介紹

● きしだ なおき(Kishida Naoki)● 来了日本的福岡● 自由工作者

Page 3: 如何用JDK8實作一個小型的關聯式資料庫系統

Blog/SNS

● Twitter– https://twitter.com/kis

● 部落格(きしだのはてな)– http://d.hatena.ne.jp/nowokay/

Page 4: 如何用JDK8實作一個小型的關聯式資料庫系統

福岡

● 日本的西邊● 九州的北邊

● 九州=大概跟台灣一樣大

Page 5: 如何用JDK8實作一個小型的關聯式資料庫系統

福岡

● 從福岡到東京跟從福岡到臺北(飛機兩個小時)

Page 6: 如何用JDK8實作一個小型的關聯式資料庫系統

内容

● 自製資料庫● 實作

– Java 8 使用到的功能

– 其他程式庫

Page 7: 如何用JDK8實作一個小型的關聯式資料庫系統

自製的資料庫● 主要用途是為了學習● 關聯式資料庫● 沒有資料形態● 單執行

– 多執行是複雜● 沒有網路● 記憶體上運作

– 不會存取到檔案系統

● github– https://github.com/kishida/sqlparser

Page 8: 如何用JDK8實作一個小型的關聯式資料庫系統

資料庫的構造

● Parser● Planner● Optimizer(最佳化)

– Index

● Executor– Transaction

Page 9: 如何用JDK8實作一個小型的關聯式資料庫系統

Parser

● 字串表示的 SQL 剖析

● 製作 AST 抽象語法樹

● 使用了 JParsec 來實作

Page 10: 如何用JDK8實作一個小型的關聯式資料庫系統

Planner

● 抽象語法樹後 生邏輯執行計劃產● 邏輯執行計劃

– 詢的處理順序,用關聯式代數表示查● 關聯式代數

– 關聯式資料庫的基礎

Page 11: 如何用JDK8實作一個小型的關聯式資料庫系統

Optimizer

● 將邏輯執行計劃製作物理執行計劃● 最佳化

– 節省不必要的處理

– 決定要使用的 index● 規則為基礎的演算法

– 用來設定好規則使用 index– 難支援複雜的 詢查

– 依照資料的分佈狀況,效率不好的狀況

→cost based 的演算法

Page 12: 如何用JDK8實作一個小型的關聯式資料庫系統

物理執行計劃執行

● Transaction● MVCC

– MultiVersionConcurentControl

● 沒 commit 的資料不會被其他 transaction 看到

Page 13: 如何用JDK8實作一個小型的關聯式資料庫系統

Java8的効能

● Stream● Optional

Page 14: 如何用JDK8實作一個小型的關聯式資料庫系統

● 生新的 產 List

● 將List 中的資料處理後 生新的 產 List

– fields 的 List

– 所有 執行 值 eval 的方法

List<Value> result = new ArrayList<>();for(Field f : fields){ result.add(eval(f));}

Page 15: 如何用JDK8實作一個小型的關聯式資料庫系統

● 生新的 產 List

● 用Stream● 這種類似處理非常多

● 使用 Stream 可以減輕很多負擔

List<Value> result = fields.stream() .map(f -> eval(f)) .collect(toList());

Page 16: 如何用JDK8實作一個小型的關聯式資料庫系統

●判斷List

● List 的所有元素是否都符合條件的判斷

– conditions 的 List

– 元素在使用 hasOr

– 所有true 的話就 return

boolean result = true;for(Condition c : conditions){ if(!hasOr(c)) result = false;}if(result) return;

Page 17: 如何用JDK8實作一個小型的關聯式資料庫系統

●判斷List

● 使用Stream– 一行就可以

– 可以在 if 直接使用

– 減少不必要的 result 變數

– 可以減少一些邏輯上出錯的問題

if(conditions.stream().allMatch(c -> hasOr(c))){ return;}

Page 18: 如何用JDK8實作一個小型的關聯式資料庫系統

Optional

● 表示有沒有 的型別值

● Scala→Optiona、Haskell→Maybe● 通常使用 null

– 忘記做 null 檢 →查 NullPointerException– 從程式碼型別上根本就分辨不出來,變數有沒

有可能被指定成 null 的狀況

Page 19: 如何用JDK8實作一個小型的關聯式資料庫系統

Optional

● ex:BufferedReader– readLine

● 沒有資料可以讀時會回傳 null● 不會知道他有可能回傳 null● 必須認真看文件

– 文件● 忘記寫● 常常 懶沒寫偷

– 忘記檢 查 null→NullPointerException

● 使用 Optional 就可以減少這類 NullPointerException 的狀況

Page 20: 如何用JDK8實作一個小型的關聯式資料庫系統

Optional 的使用方法

● 建立 Optional– Optional.of(value)

– null 的時候, 會 生產 NullPointerException

– 參數不為 null 時才可以使用

● 不知道是不是 值 null– Optional.ofNullable(value)

● 表示沒有值

– Optional.empty()

Page 21: 如何用JDK8實作一個小型的關聯式資料庫系統

從 Optional 取得值1

● get()

– 沒有值,丟出 NoSuchElementException– 請儘量不要這樣使用

● orElse(defaultValue)

– 沒有 時會回傳 值 defaultValue

Page 22: 如何用JDK8實作一個小型的關聯式資料庫系統

從 Optional 取得值2

● orElseGet(() -> defualtValue)

– defaultValue 的計算可能會花一些時間

– 傳入一個型別為 Supplier

– 使用 lambda 式– 沒有 的時候才會執行值

– 只有在需要時才執行的動作● 延遲執行(Lazy Execution)

Page 23: 如何用JDK8實作一個小型的關聯式資料庫系統

Optional 有 得時候才會想要執行某值些動作

● 判斷有沒有值

● isPresent()

– 有 →值 true

– 沒有值(empty)→false● 不是 Java 8 的風格

Optional<String> ostr = Optional.ofNullable(str);if(ostr.isPresent()){ System.out.println(ostr.get().length());}

Page 24: 如何用JDK8實作一個小型的關聯式資料庫系統

Optional 有 得時候才會想要執行某值些動作

● ifPresent(Consumer c)● 只有在有 時會執行傳入的式值

● 參數的型別是Consumer

– 用 lambda 來寫

– 有 時才會執行值

Optional<String> ostr = Optional.ofNullable(str);ostr.ifPresent(s -> { System.out.println(s.length());});

Page 25: 如何用JDK8實作一個小型的關聯式資料庫系統

轉換成其他值 值● map(Function<T, U>)

– 傳入回傳普通 的 值 lambda 式

– 回傳包著那個 得 值 Optional

– null的時候,變成empty

– 不用擔心 NullPointerException● flatMap(Function<T, Optional<U>)

– 傳入回傳Option的 lambda式

– 回傳剛剛的 OptionalOptional<String> ostr = Optional.ofNullable(str);ostr .map(String::length) .ifPresent(System.out::println);

Page 26: 如何用JDK8實作一個小型的關聯式資料庫系統

當 符合條件才要處理值

● filter(Predicate<T>)

– 條件不符合會回傳 empty

Optional<String> ostr = Optional.ofNullable(str);ostr .map(String::length) .filter(len -> len < 5) .ifPresent(System.out::println);

Page 27: 如何用JDK8實作一個小型的關聯式資料庫系統

map,filter,ifPresent

● 跟 map 還有 filter 之類的方法搭配處理時,非常有效果

● map・filter・ifPresent裡面

– 保證 不會是 值 null

– 不用擔心NullPointerException● 隔離有 null 的世界和沒有null 的世界● Optional要多打一些字 (^^

– 可以讓人寫的比較安心

– 請記得會出現 null 時就要利用 Optional

Page 28: 如何用JDK8實作一個小型的關聯式資料庫系統

程式庫

● Lombok● JParsec

Page 29: 如何用JDK8實作一個小型的關聯式資料庫系統

Lombok● http://projectlombok.org/● 可以把一些 Java 很繁雜的程式碼減少

● Setter/Getter

– 可以用 IDE 幫我們 生產

– 看起來一長串很煩

– 改也很麻煩

class Foo{ String message; public String getMessage(){ return message; } publilc void setMessage(String m){ this.message = m; }}

Page 30: 如何用JDK8實作一個小型的關聯式資料庫系統

Lombok

● 清爽許多

class Foo{ @Setter @Getter String message;}

Page 31: 如何用JDK8實作一個小型的關聯式資料庫系統

Lombok

● @NoArgsConstructor– 生預設建構子產

● @AllArgsConstructor– 成員變數都要設定的建構子

● @ToString– 生 產 toString

● @EqualsAndHashCode– 生 產 equals 和 hashcode

● 對應 IDE

Page 32: 如何用JDK8實作一個小型的關聯式資料庫系統

JParsec

● http://jparsec.codehaus.org/● Parser Generator

– 産生抽象語法樹

● Haskell的Parsec移植● 用Java做 parser

– JavaCC和Antlr需要 Java 程式碼以外的語法定義檔

– 必須特別編譯

● 用 Java 來定義語法

– 不需要額外的檔案和編譯

Page 33: 如何用JDK8實作一個小型的關聯式資料庫系統

JParsec的例

● delete的語法定義

public static Parser<ASTDelete> delete(){ return Parsers.sequence( terms.token("delete").next(terms.token("*").optional()) .next(terms.token("from")).next(identifier()), where().optional(), (id, w) -> new ASTDelete(id, Optional.ofNullable(w))); }

Page 34: 如何用JDK8實作一個小型的關聯式資料庫系統

總結1

● 製作資料庫非常有幫助

– 資料庫的構造● MySQL、PostgreSQL、Oracle● 能大概知道他們到底在做什麼

– 能了解 SQL 的處理過程

● 可以寫出效率更好的 SQL

Page 35: 如何用JDK8實作一個小型的關聯式資料庫系統

總結2

● Java8很方便

– 回不去Java7● Optional應該多加利用

– Java8中如果出現 nullpointerexception 就太失敗了

● Lombok– 可以從又臭又長麻煩的程式碼中解脫

● JParsec– 不知不覺的完成結構很大的語法定義,很有趣