Open6

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

philosophynotephilosophynote
  • テーブルやレコードの中身がわかる適切な中身をつける
  • 外部キー製薬やCHECK制約を利用してデータを適切に防ぐ
  • リレーショナルモデルに基づいた設計を心がける

CHECK制約便利そうだけどバージョンの関係で使用できない

  • 値が変更になる場合は履歴テーブルを作成する
    マテリアライズド・ビューとは何か

https://qiita.com/wanko5296/items/61c3e6ec4561b26beb5c

履歴分だけパフォーマンスが低下するため、遅延レプリケーションやElasticsearchなどの分析ツールの使用を検討する

philosophynotephilosophynote

JOINには3つのアルゴリズムが存在する

https://zenn.dev/captain_blue/articles/three-types-of-join-algorithms

JOINの改善としては、JOIN対象テーブルの整理やINDEXの利用、Viewの活用が考えられる

RDBMSがINDEXを使用しないケースは次の通り

  • 検索結果が多い、全体の件数が少ない
    INDEXを利用するためには次の2つの条件が必要
     ①検索結果がテーブル全体の20%未満
     ②検索対象のテーブルが十分に大きい
  • 条件にその列を使っていない
     条件のカラムに数式を用いたり、関数を使用する場合
  • カーディナリティの低い列に対する検索
     カーディナリティ:「列に格納されるデータの値にどのくらいの種類があるのか?」
  • あいまいな検索
    LIKE検索:後方一致と部分一致では使用されない
  • 統計情報と実際のテーブルで乖離がある場合

https://qiita.com/Nyokki/items/07a3afab8671de522b03

philosophynotephilosophynote

削除フラグは次の問題を含んでいる

  • クエリの複雑化(SELECTする際にJOINやWHEREをつける必要がある)
  • UNIIQUE制約が使えない
     データの重複が防げない
     該当列に対して外部キー制約を利用できない
     外部キー制約を利用できないことでデータの関連性を担保できない
  • カーディナリティが低くなる

解決策
トリガーを利用して削除済みテーブルを作成する
Viewを活用する
まず状態を持たせるべきか考える、次の点について考える

  • 対象のテーブルが小さく、INDEXが不要
  • そのテーブルが関連するテーブルの親になることがなく、データを取得する際に頻繁にJOINの対象になることがない
  • UNIQUE制約が不要で、外部キーでデータの整合性を担保する必要がない

削除フラグを利用したくなるケース

  • エンドユーザから見えなくしたいが、データは消したくない
  • 削除したデータを検索したい
  • データを消さずにログに残したい
  • 操作を誤ってもなかったことにしたい
  • 削除してもすぐに元に戻したい

https://www.slideshare.net/yoku0825/mysql-52276506?qid=3e4580d5-d49e-44f9-bb53-d5dce830c49b&v=&b=&from_search=7

https://www.slideshare.net/SoudaiSone/postgre-sql-54919575

https://www.slideshare.net/t_wada/ronsakucasual

philosophynotephilosophynote

リレーショナルモデルの世界にはソートがない

〜句 内容
from テーブル指定
on カラム指定
join テーブルの結合
where 条件指定
group by グループ化
sum,avgなど 関数
having 集計後の絞り込み
select, distinct 検索
order by 並べ替え
limit 取得件数の指定

全てのデータを取り出してからORDER BYで並べ替え、最後にLIMITで必要なデータを切り分ける
データを取り出してからバラバラのデータを並び替えるため、ソートは高コストな処理ですし、
実際のデータを大きくなればなるほど、さらに重い処理になる。

解決策
1.WHERE句狙いのINDEX
WHERE句を利用してデータを絞り込んでからソートする
2.ORDER BY句狙いのINDEX
1の場合はカーディナリティが少ない場合はINDEXが適用されない場合がある

その他アプリ側でソート、結果をキャッシュする、NoSQLの利用が考えられる

r-sugir-sugi

私も「失敗から学ぶRDBの正しい歩き方」をきっかけに、最近RDBのテーブル設計について学んでいます。とても参考になりました!

「失われた事実」「隠された状態」「フラグの闇」の解決案をあれこれ考えて記事にしてみました。
もしよかったら、いいね、コメント、ツッコミをもらえると嬉しいです!
https://zenn.dev/rsugi/articles/8a939d7bd2f60a