書籍概要

Software Design plus

失敗から学ぶ RDBの正しい歩き方

著者
発売日
更新日

概要

「データベースがよく落ちる」「前任者が残したテーブル,SQLが読み解けない」「RDBMSを入れ替えたら予期せぬバグが」――MySQLやPostgreSQLといったRDBMS(リレーショナルデータベース管理システム)を使った業務システム,Webサービスを設計・運用していると,こういった問題によく直面するのではないでしょうか。
本書はRDB(リレーショナルデータベース)の間違った使い方(=アンチパターン)を紹介しながら,アンチパターンを生まないためのノウハウを解説します。それぞれの章では,問題解決に必要なRDBやSQLの基礎知識も押さえるので,最近RDBMSを触り始めた新人の方にもお勧めです。

こんな方におすすめ

  • MySQLやPostgreSQLを使ったシステム・サービスを設計・運用していて,原因のわからない障害によく出くわす人,そしてそれを改善したい人

サンプル

samplesamplesample

目次

第1章 データベースの迷宮

第2章 失われた事実

第3章 やり過ぎたJOIN

第4章 効かないINDEX

第5章 フラグの闇

第6章 ソートの依存

第7章 隠された状態

第8章 JSONの甘い罠

第9章 強過ぎる制約

第10章 転んだ後のバックアップ

第11章 見られないエラーログ

第12章 監視されないデータベース

第13章 知らないロック

第14章 ロックの功罪

第15章 簡単過ぎる不整合

第16章 キャッシュ中毒

第17章 複雑なクエリ

第18章 ノーチェンジ・コンフィグ

第19章 塩漬けのバージョン

第20章 フレームワーク依存症

サポート

正誤表

本書の以下の部分に誤りがありました。ここに訂正するとともに,ご迷惑をおかけしたことを深くお詫び申し上げます。

(2024年1月24日最終更新)

P.188 図14.4 トランザクションB

INSERT INTO 商品 VALUES (:id, :名前, :価格);
INSERT INTO 商品 VALUES (:id, :名前, :価格);
COMMIT;

(以下2023年12月19日更新)

P.138 本文下から6行目

成功していたしても
成功していたしても

(以下2022年9月20日更新)

P.204 1行目

CREATE TABLE 県 (件名 enum('北海道','青森','岩手' .... '沖縄');
CREATE TABLE 県 (名 enum('北海道','青森','岩手' .... '沖縄');

(以下2022年8月15日更新)

P.202 図15.5 8,11行目

> postgres(# WHEN "好きなデータベース"!='そのほか' AND "そのほか"='' THEN TRUE
> postgres(# WHEN "好きなデータベース"='そのほか' AND "そのほか"!='' THEN TRUE
> postgres(# WHEN "好きなデータベース"!='それ以外' AND "そのほか"='' THEN TRUE
> postgres(# WHEN "好きなデータベース"='それ以外' AND "そのほか"!='' THEN TRUE

(以下2019年8月22日更新)

第3章 P.27

また、JOINは集合の和の結果ですので、よくベン図で表現されます(図3.2)。このように、重なり部分を取得するのがINNER JOINです。
また、JOINは集合同士の演算の結果ですので、よくベン図で表現されます。図3.2のように、重なり部分を取得するのがINNER JOINです。

(以下2019年8月19日更新)

第6章 P.80 リスト6.3 7行目

AND id > :前の表示ページの最後の行のid

AND id < :前の表示ページの最後の行のid

(以下2019年6月4日更新)

第14章 P.187 図14.2のキャプション

ファジーリードの例
ファジーリードの例(read committed)

第14章 P.187 図14.3のキャプション

図14.2でファジーリードが発生しない場合
図14.2でファジーリードが発生しない場合(repeatable read)

(以下2019年5月23日更新)

第12章 P.162

デッドロックの可否
デッドロックの有無

(以下2019年5月20日更新)

第8章 P.110

しかもJSONは値の型を指できないため、こういった型の違いを制限できません。
しかもJSONは値の型を指定できないため、こういった型の違いを制限できません。

(以下2019年4月8日更新)

第3章 P.35 リスト3.8


SELECT
  単価表1.単価 AS 単価1
  , 単価表1.会員id AS 会員1id
  , 単価表2.単価 AS 単価2
  , 単価表2.会員id AS 会員2id
FROM
  ( 
    SELECT
      単価表1.単価 AS 単価1
      , 単価表1.会員id AS 会員1id
      , 単価表2.単価 AS 単価2
      , 単価表2.会員 id AS 会員2id
    FROM
      単価表 AS 単価表1
      INNER JOIN 単価表 AS 単価表2
        ON 単価表1.単価id < 単価表2.単価id
        AND 単価表1.会員id <> 単価表2.会員id
    WHERE
      (単価表1.単価 + 単価表2.単価) > : 合計単価
  ) AS 単価組み合わせ表
  INNER JOIN 会員
    ON 会員.user_id = 単価組み合わせ表.会員1id
    AND 会員.user_id = (SELECT 会社id FROM 会社 WHERE 会社名 = '株式会社そーだい')


SELECT
  単価1
  , 会員1id
  , 単価2
  , 会員2id
FROM
  ( 
    SELECT
      単価表1.単価 AS 単価1
      , 単価表1.会員id AS 会員1id
      , 単価表2.単価 AS 単価2
      , 単価表2.会員id AS 会員2id 
    FROM
      単価表 AS 単価表1 
      INNER JOIN 単価表 AS 単価表2 
        ON 単価表1.単価id < 単価表2.単価id 
        AND 単価表1.会員id <> 単価表2.会員id 
    WHERE
      (単価表1.単価 + 単価表2.単価) > :合計単価
  ) AS 単価組合せ表 
  INNER JOIN 会員 
    ON 会員.会員id = 単価組合せ表.会員1id
    AND 会員.会社id = (SELECT 会社id FROM 会社 WHERE 会社名 = '株式会社 そーだい')

(以下2019年4月3日更新)

第6章 P.76 図6.3 中央の表

誤

正

(以下2019年3月28日更新)

第2章 P.14

RDBは、“時間軸と直行するような設計”が大切です。ですがそれを使ったサービスとしては、時間軸と直行しないデータ=履歴を保存することが同じくらい重要です。
RDBは、“時間軸と直交するような設計”が大切です。ですがそれを使ったサービスとしては、時間軸と直交しないデータ=履歴を保存することが同じくらい重要です。

(以下2019年3月20日更新)

第17章 P.228

開発者B:CASE文とサブクエリの嵐ですね……。
開発者B:CASEとサブクエリの嵐ですね……。

(以下2019年3月18日更新)

第3章 P.25 リスト3.1 2行め

 単価表1. 単価 AS 単価1
 単価表1.単価 AS 単価1

「単価表1」と「.単価」の間に余計な半角スペースがありました。

第3章 P.25 リスト3.1 9行め

    ON 単価表1.単価 id < 単価表2.単価id
    ON 単価表1.単価id < 単価表2.単価id

「単価」と「id」の間に余計な半角スペースがありました。

第3章 P.35 リスト3.8 12行め

      , 単価表2.会員 id AS 会員2id

      , 単価表2.会員id AS 会員2id

「会員」と「id」の間に余計な半角スペースがありました。

(以下2019年3月11日更新)

第2章 P.15 図2.2

誤

正

第2章 P.16 図2.3

誤

正

(以下2019年3月7日更新)

第3章 P.32

INDEX1つでこのように大きく計算結果が変わるのです。
INDEX1つでこのように大きく計算コストが変わるのです。

商品一覧