Effective SQL とは

良書が多いイメージの Effective シリーズに、Effective SQLなるものが発売されたのでとりあえず読んでみました。

Title: Effective SQL: 61 Specific Ways to Write Better SQL, First Edition
Author: John L. Viescas, Douglas J. Steele, Ben G. Clothier
Publisher: Addison-Wesley Professional
Release Date: December 2016
ISBN-13: 978-0-13-457889-7

本書の構成

全部で61個の項目が大きく10章に分かれて紹介されています。

各章の簡単な説明と、私が感じた感想などを書いておきます。

第1章 Data Model Design

EffectiveなSQLの前提として、適切なデータベースのモデリングが必要であるとして、
最初となる第1章でRDB設計の基礎的な内容と検討すべき方針などが紹介されています。

基礎的な話も多いため特に目新しい部分はありませんが、単純なトピックの紹介だけではなく、なぜ重要なのかも含め一通りは網羅されています。

なお本書はフルカラーで印刷されているため、文章の見出しやER図、SQLのキーワードなどが色分けされ比較的見やすいです。

ちなみにER図は Microsoft Accesss で作成し、そのリレーションシップの画面キャプチャが利用されているようです。

第2章 Programmability and Index Design

インデックスの重要性と活用方法が紹介されています。
インデックスの役割をWhere句でのフィルタリングだけと考えている人にとっては、学ぶべきことが多いかと。

よりEffectiveなSQLを書くためには、各DBMSの特性を理解することも重要であるとしており、この2章でも各RDMSごとのNULLの取り扱いの違いなどが紹介されています。

なので本書では、基本的に標準SQL(ISO/IEC 9075-2:2011)をベースにしてますが、以下の主要な各種DBMSでテスト済みのサンプルコードが提供されています。

  • IBM DB2
  • Microsoft Accesss
  • Microsoft SQL Server
  • MySQL
  • Oracle Database
  • PostgreSQL

書籍には掲載しきれていないコードも含めすべてGitHubにあがっているため、
普段利用しているDBMSですぐに確認することもできます。

第3章 When You Can’t Change the Design

前章までは適切なモデリングや設計についての紹介でしたが、
実務上の問題としてDB構造を容易に変更できないような場面も少なくないかと思います。

そんな状況にある場合、本章の情報が役に立つかもしれません。

私はむしろ本章を通じて、適切なモデリングの重要性を再確認しましたが。

第4章 Filtering and Finding Data

本章以降から、SQLクエリによる実装よりの話になっていきます。
4章では必要なデータを効率的に抽出するための、様々なテクニックが紹介されています。

例えばSQLでの関係除算の実現方法など、SQL初心者が必ずつまづきそうな具体例とその解法が参考になります。

また本章でもDBMSの実装による違いが解説されています。
例えば2017年3月14日に発生した注文を取得したいと思い、以下のSQLを実行したとします。
(ちなみになぜCASTではなくCONVERTを利用するかも本書で説明されています)

SELECT * FROM orderItems
WHERE orderDate BETWEEN 
      CONVERT(datetime, '2017-03-14', 120) and CONVERT(datetime, '2017-03-14 23:59:59.999', 120)

このクエリでは、SQL Serverの場合、2017年3月15日のデータも抽出されてしまいます。
普段SQL Serverを利用しない人にとってはちょっと驚くような事実かもですが、
これはSQL Serverのdatetimeの精度が3.33msであることに起因しています。

なおこの問題への対策として、本書ではDATEADDを使う方法が紹介されています。

第5章 Aggregation

第5章は本書の中で、項目数もページ数も最も多いことから、SQLを扱う上で集約を適切に理解していることが大きなポイントであることが分かります。

例えばGROUP BYを利用せずに、最大値と最小値を求める方法なども紹介されています。
この場合、可読性という表面上の話だけではなく、パフォーマンスなどの観点からも含め、知っているか知らないとでは大きな差があると思います。

またウィンドウ関数(OLAP)なども当然本書でカバーされていますが、
ROLLUPCUBEGROUPING SETといった、私は普段利用したことがない操作なども本書では触れられています。

利用するしないはさておき、自分の中での選択肢は広がりました。

第6章 Subqueries

本書では様々なサブクエリの形と、その利用方法が紹介されています。

例えば、通常以下のような相関サブクエリは、Itemsの数だけ毎回集計が発生しそうなのであまりパフォーマンスが良くなそうに見えます。

SELECT Items.Name,
       (SELECT COUNT(*) FROM Orders
       WHERE Orders.ItemID =  Items.ID) AS OrderCount
FROM Items

しかし実際には、
全体を結合してから集約するようなクエリに対して、相関サブクエリを利用した方がパフォーマンスが良くなる状況も存在します。
さらにデータによっては結果も異なるので、パフォーマンス以外の理由でもサブクエリを採用すべき状況は存在します。

もちろんインデックスの設定状況などにも依存するため、現実には第7章にあるように、実行計画等による検証が必要でしょうが、常にひとつのやり方に固執しないことが重要だと感じます。

第7章 Getting and Analyzing Metadata

第7章では実行計画やメタデータの取得方法が各RDMSごとに紹介され、あわせて実行計画の読み方についても解説されています。

本書で紹介されている事項がすべての状況下で常に有効とは限らないため、実務に適用するに当たっては実行計画を理解する力が必要になってきます。

本章では図書館で本を探すという動作に置き換えて、SQLの内部的な動作が細かく説明され、その上で実行計画の読み方が解説されています。

具体的な実行計画の説明は SQL Server のみですが、基本はどのDBMSでも変わらないはずです。
私は現在たまたま SQL Server を利用していることもあり、IndexSeekIndexScanKey Lookup などの意味を改めて理解する良い機会になりました。

第8章 Cartesian Products

あまり業務で利用する機会が少ない、クロス結合による直積の使いどころが紹介されています。

私は主に帳票などのヘッダ情報を生成するような場面のみで利用していましたが、それ以外の利用方法に関してもちょっと紹介されています。

いずれにしてもあまり理由する機会は少なそうですが、過去に書いたクエリがクロス結合で、もっとすっきり記述できた場面がある気がしてきました。

第9章 Tally Tables

Tally Table とは、以下のような連番で構成されるようなテーブルであり、複雑なクエリの補助テーブルとして利用されます。

Seq
1
2
3
:
10

ここでは先入れ先出し法での株価の損益計算の例など紹介されていますが、パッと見ではどう書けばよいか分からない問題も、Tally Tableを使うことでスマートに記述できることが分かります。

また単純な数列だけではなく、あらかじめ計算した結果テーブルを利用したり、ピボット用のテーブルを用意するといったテクニックなども本章に含まれます。

なおこの章に限ったことではありませんが、本書では他の項目で紹介した事実やテクニックなどが随所で利用され、その都度、参照先の項目も明記されています。

このことからも、EffectiveなSQLのためには、包括的な理解が必要であることがわかります。

第10章 Modeling Hierarchical Data

RDBで階層的なデータ構造を表現するため、よく利用されている4つの表現モデルが紹介されています。

  • 隣接リスト
  • 入れ子集合
  • 経路実体化モデル
  • 閉方テーブル

参考になる内容ではありますが、実際には既にすべて知っている内容でした。

最後にその理由を述べておきます。

他の参考書籍

実は品薄で本書が手に入るまで時間がかかったこともあり、予習として事前に以下の書籍を読んでいたため、いきなり最初に本書を読む人とは感想も変わってくると思われます。

なので、以下実際に読んだ順序で紹介しておきます。

SQL実践入門

Title: SQL実践入門──高速でわかりやすいクエリの書き方
Author: ミック
出版社: 技術評論社
Release Date: 2015/4/11
ISBN-13: 978-4774173016

本書はタイトルどおり、より実践的なテクニックが紹介されています。

実行計画を根拠に各クエリが解説されているため、どんな環境でも効率的なクエリを記述できるテクニックを学べます。

分かっているつもりでも、実はちゃんと理解できていなかったことも結構ありました。
例えばなぜ内部結合という名前なのか、そういえばちゃんと分かっていませんでしたし、またCase式やウィンドウ関数を過小評価してたことに気づかされました。

達人に学ぶ SQL徹底指南書

Title: 達人に学ぶ SQL徹底指南書
Author: ミック
出版社: 翔泳社
Release Date: 2008/2/7
ISBN-13: 978-4798115160

SQL実践入門と同じ著者による書籍ですが、リリースされた時期が古いため、完全に読む順序を間違ったなと思いました。

よってこちらの本ではウィンドウ関数などがあまり出てきませんが、当時のDBMSでの実装状況が完全に追いついていなったことが影響しています。

本書はSQLの背景にある集合論と述語理論を通じて、理論的な説明によってSQLとは何かを学ぶことができました。

実は関係除算の概念を本書で初めて意識するようになったり、なぜSQLには関係除算が存在しないかなど、単純に読み物としても興味深い話が多いです。

特に3値理論とNULLの話は面白く、NULLに対する見方が変わりました。

SQL実践入門と同じ著者ということで、特性関数の使い方や手続き型からの脱却の必要性など、主張する内容は一貫しているので読みやすく参考になりました。

SQLアンチパターン

Title: SQLアンチパターン
Author: Bill Karwin, 和田 卓人, 和田 省二, 児島 修
出版社: オライリージャパン
Release Date: 2013/1/26
ISBN-13: 978-4873115894

SQLアンチパターンは題名のとおり、実際にやりがちなアンチパターンが、これまた一定のパターンに沿って紹介されています。

DB設計やクエリの話だけなく、アプリケーション開発時のアンチパターンまで網羅されているのが印象的でした。

同じようなアンチパターンをすでに経験している人にとっては、非常にわかりやすい内容になっているかと思います。

このあたり、理論から説明されているミック氏の2冊とは異なるアプローチであり、どの書籍が一番良いかは人によって異なるため、実際に手にとって見るのが一番かと思います。

なおEffective SQLの10章の内容を既に知っていたのは、このSQLアンチパターンにも同様の内容が記載されているためでした。

まとめ

  • ページ数はそれほど多くないが(300ページほど)幅広い分野をカバー
  • 内容的にはそれほど難しくなく、初心者の方でも読み進められるはず
  • とはいえ長年SQLを書いてきた人でも気づきがあるはず
  • 各DBMSごとの違いも説明され、ソースはgithubから取得可能
  • フルカラー
  • 英語

ちなみに、英語の勉強がてら読んでみよう思った部分もありましたが、事前の予習の効果もあってか、私には読みやすい英語でした。

結局4冊ほど紹介してしまいましたが、本は読み手との相性もあるかと思いますので、あくまで私の感想ということで。

(ちなみに私はSQL実践入門との相性が良かったです)