Yabu.log

色々勉強するブログです

プログラマのためのSQL 読書会(15)に参加

15章を読みました

感想

初参加です。本の読み具合はちょうど4割、と言うところ。 本書の日本語訳は第4版ですが、原著は5版まで出ているようです。

パフォーマンスとか内部の動きってどうしても「実装に依存する(キリッ」となり話が終わりがちですが、 参加者の皆さんの経験が豊富で、いろんな観点からの事例・各RDBMSの話を拝聴することができ、大変充実した2時間となりました。

私はDBスペシャリスト勉強中 + ミックさんが関わっている本を結構読んでる*1 くらいの知識なので、どれかのRDBMS固有のディープな知識はないので、色々知ることがありました(特にMySQL)

DB2SQLServerのウェートは少なかったような? その2つ詳しい人が来れば面白いかもしれません。

ちなみにSQLiteの話は一度も出ませんでした

カーソル

本書にもカーソルを推奨していない書き方をしている箇所があったり、 カーソルは旧時代の遺物で使う必要のないものだと勝手に思い込んでいたので、思い切って聞いてみました。

  • ストアドでは使った方が良い。
  • 同じテーブルを何回もスキャンするようなクエリ

同じテーブルをなんどもスキャンしているクエリでは カーソルで処理した方が効率が良い、と言う説明は納得がいきました。

delete文ではtableの別名は使えない

DELETE FROM Personnel AS B1
 WHERE Personnel.boss_nbr = B1.emp_nbr
  AND Personnel.salary > B1.salary;

FROM句でつけた名前を使った複雑な相関サブクエリは利用できない。

遅延制約の使い道

  • テストデータの用意。
  • バッチだと制約が重くなる。

遅延制約は以前から知っていたが、自分なりに感じていたメリットは レコードを削除させる順番に柔軟性を持たせられる・・・と言うもの。 これだとちょっと設計が雑な気がする。

バッチで処理中に一々制約のチェックが入ると重くなるので、 バッチに関しては遅延制約が有効とのこと。

UPDATE文に行構築子が使える

UPDATE Foobar
 SET (a,b,c) = (1,2,3)
WHERE x < 12

右辺にクエリが書けるね、と言う意見がでた。 行構築子と言う言葉は知らなかった。調べてみたらテーブル構築子と言う単語もあるようだ。

主キーのないテーブルは結構ある。

主キーがないと、mysqlだとレプリケーションが死ぬ。。。 私も一度主キーのないテーブルを作らされたことがあるが、 主キーのないテーブルは案外多いらしい。

論理削除と外部参照性制約

論理削除フラグを使っているプロジェクトには参照制約が貼れない(活用できない)。

誤記?

15.1.5に

参照整合制約を使わずに複数のテーブルから削除する 1.削除する値を持った一時テーブルを使う。 2.参照整合制約のCASCADEオプションを使う 3.ビューまたは規定テーブルのINSTEAD OFトリガーを使う。

とありますが、2って結局参照整合制約使ってるじゃないか!と言う鋭いツッコミがありました。

トリガーとcascade

とあるRDBMSでは小テーブルのdeleteトリガーは、親テーブルの削除の連鎖をトリガーしない。

トリガーは色々問題を起こす。

トリガーはスタックを使いながらやるので、 大きなトリガーはトラブルのもと。

update非推奨派

そう言う派閥があると@makopi23さんに教えてもらいました。

http://makopi23.blog.fc2.com/blog-entry-176.html

SQLアンチパターンの和田省二氏さんがその派閥だそうです。

システム時間を表す予約語は色々なタイプがある。

  • トランザクションの開始時
  • バラバラ
    • 行の中では同じ。
    • 列でバラバラ
  • 文の中では同一になる。

SYSDATEくらいしか使ったことがないけど、ここはドキュメントをきちんと確認しようと思う。

bulk insertは標準ではない。

便利だが標準ではない。 https://qiita.com/bunty/items/91283160b0a38956655e

Oracleのbulk inertしか知らなかったが、MySQLならかなりシンプルに書ける。

バルクロードはSQLを介さずにデーターを直接入れるAPIを使っている(多分)

SQLがいちいちパースされないので、実行が早い。

交換のクエリは実装依存

実際に主キーを交換するクエリは失敗するDBMSがあった。 MySQLは左から順番にやっていくため成功しないらしい*2

オートコミットモードは怖い。

オートコミットモードにもサーバー設定とクライアント設定がある。 過去にサーバー側でオートコミットモードを必ず使う必要のあったDBMSではクライアント側で設定していた模様。

最近私もオートコミットな職場で働いているが、検証環境とわかりつつヒヤヒヤしてしまう・・・

15.4ベンダー拡張が持つ欠陥について

最近は治っている。らしい

merge(upsert)

かなりシンプルにUPSERT文が使えるDBMSの経験があるので

「merge文って結局アプリケーション側のコードでおこなるINSERT or UPDATEの切り替えを SQLで書くだけで、実質クエリは2つ書かないと行けないし、ちょっと冗長な気がしますね。」

と発言したところ

mysql

  • on dupulicate
  • replace into *3
  • effected rowsを教えていただいた。

mysqlは急進的?と言うか結構色々実験的なことをやっているらしい。

ほか

*1:パズル、グラフ理論、雑誌の連載など以外はだいたい読んでるような

*2:検証していません

*3:トリガーと相性が悪いので非推奨