2017-03-28

Tagging System Design

Tagging 也算是目前系統中常見的功能,實作上也被討論了不少,大致上分底下 3 種類型:
  1. Denormalized solution
    Pros:
    • 單一 table 易於直接人工閱讀資料與維護。
    Cons:
    • 所有 tag value 集中於一個 cell,需要保留一特殊字符作為分隔使用。
    • 查詢時將大量使用 LIKE,查詢條件字串組成受限;但效能上可能優於 JOIN [1]。
  2. Entity-Relation solution
    Pros:
    • 使用獨立的 table 專門紀錄 tag value 與 entity 對應的關係。
    • 個別 tag value 被拆分為獨立記錄,不需要保留特殊字符,也不會大量使用 LIKE 運算。
    Cons:
    • 必須嚴格確保每一個 entity id 與 tag value 組合只會存在一筆記錄;否則使用 HAVING-COUNT 查詢時會出現錯誤。
    • Tag 本身無法帶有其它屬性,例如:引用次數/日期、從屬關係、有效與否、與內部/顯示名稱等。
    • Tag 更名時需要更新大量資料。
  3. Intersection Table solution
    Pros:
    • 所有的 tag value 獨立一個 table 存放,易於統整 tag value 或更名。
    • Tag 本身被視為另一個獨立的 entity,可自由定義屬性。
Cascade Updates: 當使用 normalized solution 時,寫入時需要 cascade updates 往往是需特別注意的地方,但只要程式邏輯無誤,便不會產生 orphan relation/entity 的情形。

Tag vs. Category

  • Tag 是 many-to-many 的關係,category 是 one-to-many。
  • Tag 一般不實作階層式結構。階層式結構必須搭配 recursive search 才有效果,也就是以 parent tag 搜尋時,結果應包括與 child tag 關連的項目;但一般像 GMail 雖然表面上具備階層式的 label,實質上卻沒有 recursive search 的能力,屬於 一種 faux hierarchical tagging。

另外 [2] 提到 3 種常見的 tag 使用情境:(1) 使用 tag 搜尋;(2) 透過某一文件的 tags 尋找擁有類似 tags 的其他文章;(3) 透過一群 tags 搜尋其他相關 tags。

see also:
[1] Tags: Database schema
[2] In Lieu of the Promised Article on Tags and SQL

Windows Name Resolution

名稱解析 (name resolution) 雖然是存在已久的機制,但有時候還是會遇到一些因為實作差異而導致行為不同的地方。一般在 Windows 下常用的解析工具大概有 nslookup 跟 ping,撇除 single-label server name (a.k.a. Windows host name) 隸屬於 NetBIOS/WINS 的管轄範圍,當使用這兩個工具作一般網域名稱解析,需要注意的有:

  • Windows 內建 DNS Client 服務 (service name: Dnscache),會讀取系統網路介面 (network interface) 的 DNS 設定,負責 DNS cache。
  • 當變更時網路介面 DNS 設定,DNS Client 並不見得會立即套用新設定,cache 資料也可能不會 flush。
  • ping 解析時會先向 DNS Client 查詢,因此單獨變更 DNS 設定可能導致 ping 仍然讀取到舊資料;nslookup 不透過 DNS Client 因此會直接套用最新設定查詢。
  • 可以透過系統管理介面,重新啟動 DNS Client 服務,達到套用新設定與 flush cache 的目的;單獨 flush DNS cache 可使用指令 ipconfig /flushdns
  • 當 DNS Client 無該筆資料時,DNS Client 會根據 DNS 設定向外查詢,並將結果寫回 cache;nslookup 則無 cache 機制。
  • 在 nslookup shell 中變更 default server 只會暫時有效,並不會寫回系統。
  • 重啟網路介面時,亦會會重啟 DNS Client。
  • %Systemroot%\System32\Drivers\Etc\hosts 檔案為 DNS Client cache 預載內容。
see also: ping vs. nslookup

2017-03-10

Open Session in View

突然想起以前設定過 Struts2 中某個 filter,順手把之前的筆記再重新整理釐清。

Entity Manager and Transaction Manager
  • 簡單來說,entity manager 關係到資料讀取,而 transaction manager 關係到資料寫入。
  • 但兩者並非完全脫鉤,例如:在一個 transaction 中可能要參照其他 entity 的資料,或讀取 entity 時要避免 dirty data。
  • 因此 entity 要負責追蹤資料的狀態 (entity state),提供 transaction 中使用。

Open Session in View (OSIV)
  • Open Session in View 中的 session 指的是 Hibernate session
  • 用意在於避免 view rendering 的過程中,Hibernate session 過早結束導致後續 data lazy loading 產生 LazyInitializationExceptions
  • 換言之,Open Session in View 拉長 Hibernate session 的時間,並交由 view request 控制。
  • 值得注意的是:Hibernate session 結束與否不同等於 transaction commit or rollback;在純粹讀取資料的應用,操作是不需要 transaction 保護的,若是讀寫混合,Hibernate session 關閉的時機涉及 transaction 如何向 session factory 取得 Hibernate session,getCurrentSession() or openSession(),前者由 SessionFactory 自動控制,後者才需要手動在 commit or rollback 後關閉。

主張 OSIV 為 anti-pattern 的觀點集中於:
  • OSIV 忽略 readonly 與 read-write 操作本質上的不同,不應該都由 entity 決定一次存取的資料量。
  • 直接拉長 Hibernate session 給予底層實作傾向 lazy fetch 的空間,嚴重將導致 (n+1) select issue。
  • 精細一些的作法,應該由 view 決定底層應該一次 fetch 哪些欄位的資料,使用 DTO projection,而非單純由 entity 決定一次取回的欄位數量。
  • 但此種作法將提高 view 與底層 DTO 的耦合;傳統 view 只依賴 domain model,DTO 與 view 之間互不依賴。
  • 注意:這邊指的一次存取資料量,與分頁查詢無關,分頁查詢的 query 會帶有 order 與起始/結束的 row number。
Hibernate Session and Entity Manager
  • Entity Manager 是 JPA 定義的名詞,而 Hibernate session 及 SessionFactory 則是 Hibernate 特有。
  • 一般起始的順序是:transaction manger, entity manager, Hibernate session,透過 entity manager 控制 session,避免手動控制。
see also: