勉強日記

チラ裏

SQL Antipatterns ch18 Spagetti Query

pragprog.com


Spagetti Query

Although sql makes it seem possible to solve a complex problem in a single line of code, don't be tempted to build a house of cards.

  • 種々の集計を1クエリで一度に行おうとして正しい答えを得られない

Objective: Decrease SQL Queries

  • SQLのクエリは難解で、複雑で、実行コストが高いと刷り込まれている
  • 「クエリを2回発行すると2倍まずくなる」と思ってしまう
  • 1つのクエリですべてを行おうとする

Antipattern: Solve a Complex Problem in One Step

  • SQLは非常に表現力豊か
  • 1クエリでたくさんのことをできる
  • しかし、しなければならないわけではない
  • よい考えでもない
    • 他の言語でそんなことしませんよね

Unintended Products

  • JOINで意図せぬ直積集合となってしまう
    • 【補】多対多のJOINで意図せず行が増えてしまう

As Though That Weren't Enough...

  • 1つのクエリでたくさんのことを行おうとすると
  • アプリケーションへの要求はだんだん増えていくもの
  • 要求の反映に時間がかかってしまう
  • 「クエリは少ないほうが良い」というのは同じ複雑さの場合の話
  • 単一の化け物じみたクエリの工数コストは指数関数的にかさむ

How to Recognize the Antipattern

  • こんなのが聞こえてきたら注意
    • 「なんで総和と行数がこんなに大きいんだ」
      • 意図せぬ直積が生じ、掛け算されている
    • 「一日中この化け物クエリと戦っている」
      • SQLは難しいものではない
      • 1つのクエリに長くてこずるようならアプローチを再考したほうが良い
    • 「集計レポートに何も追加できない。長すぎて改修方法がわからないから」
      • 他の誰も保守できないような複雑なSQLは書くな
    • 「ここにもDISTINCTを入れてみろ」
      • 意図せぬ直積集合を握りつぶしている可能性
        • RDBMSの負荷になってしまう
  • 実行時間が長いクエリにも要注意
    • 1度の複数のことをしているため長い

Legitimate Uses of the Antipattern

  • F/Wやライブラリの要請

Solution: Divide and Conquer

  • 結果が同じならシンプルな方を選べ

One Step at a Time

  • クエリを分割する「エレガントでない」方法のメリット
    • 意図せぬ直積が生じない
    • 新しい要件が追加されたら、新しいSQLクエリを1つ追加するだけで済む
    • 最適化が効き、正味では実行速度も上がるかも
    • コードレビュー等で説明しやすい

Look for the UNION Label

  • 同種の集計結果をUNIONで1列にまとめ、行別に結果を取得する
  • 列名がbugcount_or_custoerid_or_null等になる場合は、関係ないものを無理やりまとめてしまっているので気をつける

Writing SQL Automatically - With SQL

  • SQLの問い合わせを使って大量のUPDATE文を自動生成した話
  • 実行時効率と、「仕事を終える」という目標とを勘案して最善の手段を選べ
    • 【補】悩む時間、デバッグ時間等を考慮すると、パフォーマンス最速が最善とは限らない

英語

  • intricate
    • 複雑な