データベース - 未経験から実務レベルへ|PHP初心者向け実践学習ブログ https://phpl4b.com Sat, 25 Apr 2026 01:26:00 +0000 ja hourly 1 https://wordpress.org/?v=6.9.4 https://phpl4b.com/wp-content/uploads/2026/04/cropped-スクリーンショット-2026-04-16-22.09.40-32x32.png データベース - 未経験から実務レベルへ|PHP初心者向け実践学習ブログ https://phpl4b.com 32 32 第30回: 本番運用チェックリスト(MySQL版) — リリース前に必ず確認すべき6つの観点 https://phpl4b.com/486/?utm_source=rss&utm_medium=rss&utm_campaign=30_%25e6%259c%25ac%25e7%2595%25aa%25e9%2581%258b%25e7%2594%25a8%25e3%2583%2581%25e3%2582%25a7%25e3%2583%2583%25e3%2582%25af%25e3%2583%25aa%25e3%2582%25b9%25e3%2583%2588mysql%25e7%2589%2588 Sat, 25 Apr 2026 00:00:00 +0000 https://phpl4b.com/486/ 障害の多くは、機能のバグよりも「バックアップが取れていなかった」「スロークエリの監視がなかった」「権限が過剰だった」といった設定漏れや運用の穴から発生します。本番に出す前にチェックリストを持っておくことで、こうした抜け漏れを事前に防ぐことができます。

The post 第30回: 本番運用チェックリスト(MySQL版) — リリース前に必ず確認すべき6つの観点 first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第30回: 本番運用チェックリスト(MySQL版) — リリース前に必ず確認すべき6つの観点

章: 第6章: セキュリティと本番運用

本番リリース後に「あの設定を確認していなかった」と後悔した経験はありませんか?

障害の多くは、機能のバグよりも「バックアップが取れていなかった」「スロークエリの監視がなかった」「権限が過剰だった」といった設定漏れや運用の穴から発生します。本番に出す前にチェックリストを持っておくことで、こうした抜け漏れを事前に防ぐことができます。

MySQL本番運用のチェックリストをカテゴリ別に整理し、毎回のリリース前に確認する習慣を作りましょう。

本番運用チェックリスト:カテゴリ別

カテゴリ チェック項目 確認コマンド・手段
バックアップ 定期バックアップが自動取得されているか mysqldump / クラウドスナップショット
バックアップ 復元テストを実施済みか バックアップから別環境で復元して確認
監視 スロークエリログが有効か SHOW VARIABLES LIKE 'slow_query_log';
監視 監視アラートの通知先が有効か CloudWatch / Datadog / PagerDuty など
セキュリティ DBユーザーの権限が最小化されているか SHOW GRANTS FOR 'user'@'host';
セキュリティ rootのリモートログインが無効か SELECT host, user FROM mysql.user;
パフォーマンス 主要テーブルのインデックスが妥当か EXPLAIN でフルスキャンがないか確認
設計 文字コードが utf8mb4 に統一されているか SHOW FULL COLUMNS FROM テーブル名;
設計 NULLの設計意図がドキュメント化されているか テーブル定義書・コメント
運用 マイグレーションのロールバック手順があるか 手順書・スクリプト

チェックポイント: チェックリストは「一度作って終わり」ではありません。障害が起きたとき・新しいリスクを発見したときに項目を追加し、チームで定期的に見直す運用を続けてください。

実際のコードサンプル


# MySQL本番チェック
# - [ ] バックアップ取得と復元テストが完了
# - [ ] スロークエリログを監視中
# - [ ] 権限が最小化されている
# - [ ] 主要テーブルのインデックスが妥当
# - [ ] 監視アラートの通知先が有効

まとめ & 次のステップ

  • バックアップ・監視・セキュリティ・パフォーマンスの4カテゴリを毎回のリリース前に確認する
  • 「復元テスト未実施のバックアップ」は存在しないのと同じ。定期的に復元テストを実施する
  • 監視アラートは設定するだけでなく、通知先が有効かを確認する
  • チェックリストはチームで共有し、属人化しない運用フローに組み込む
  • 障害が起きたらチェックリストを更新し、同じ失敗を繰り返さない仕組みを作る

これでMySQL上級編の第6章「セキュリティと本番運用」が完了です。権限管理・SQLインジェクション対策・スロークエリ改善・レプリケーションという実務直結の知識を体系的に習得できました。ここまで学んだ知識を実際のプロジェクトに活かしてみてください。

The post 第30回: 本番運用チェックリスト(MySQL版) — リリース前に必ず確認すべき6つの観点 first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第29回: レプリケーションの基礎 — 単一DB構成の限界に備える読み取り分散設計 https://phpl4b.com/484/?utm_source=rss&utm_medium=rss&utm_campaign=29_%25e3%2583%25ac%25e3%2583%2597%25e3%2583%25aa%25e3%2582%25b1%25e3%2583%25bc%25e3%2582%25b7%25e3%2583%25a7%25e3%2583%25b3%25e3%2581%25ae%25e5%259f%25ba%25e7%25a4%258e Fri, 24 Apr 2026 00:00:00 +0000 https://phpl4b.com/484/ 単一のMySQLサーバーにすべての読み書きが集中している構成では、サーバー障害時にサービスが完全停止します。また、アクセスが増えるにつれて読み取りクエリの負荷が書き込みを圧迫し、全体のパフォーマンスが低下する問題も起きます。

The post 第29回: レプリケーションの基礎 — 単一DB構成の限界に備える読み取り分散設計 first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第29回: レプリケーションの基礎 — 単一DB構成の限界に備える読み取り分散設計

章: 第6章: セキュリティと本番運用

DBサーバーが1台だけ、もし障害が起きたらどうなりますか?

単一のMySQLサーバーにすべての読み書きが集中している構成では、サーバー障害時にサービスが完全停止します。また、アクセスが増えるにつれて読み取りクエリの負荷が書き込みを圧迫し、全体のパフォーマンスが低下する問題も起きます。

レプリケーションを導入すると、PrimaryがReplicaにデータを非同期で同期し、読み取りをReplica側に分散させることができます。 可用性の向上とパフォーマンス改善を同時に実現する基礎技術です。

レプリケーションの構成パターンと特徴

構成 読み取り分散 書き込み冗長化 複雑さ 向いているケース
単一インスタンス 不可 なし 開発・小規模サービス
Primary-Replica(1対1) 可(Replicaで読む) 手動フェイルオーバー 中規模サービス・読み取り負荷が高い場合
Primary-Replica(1対多) 可(複数Replicaに分散) 手動フェイルオーバー 中〜高 大規模な読み取り負荷分散
Group Replication / InnoDB Cluster 自動フェイルオーバー 高可用性が必須の本番環境

チェックポイント: レプリケーション遅延(Replica Lag)に注意してください。書き込み直後のデータをReplicaから読み取ると古いデータが返ることがあります。書き込み後すぐに読み取りが必要なフローは、Primaryから読む設計にしてください。SHOW REPLICA STATUS\GSeconds_Behind_Source で遅延を監視します。

実際のコードサンプル


-- レプリカ状態確認(例)
SHOW REPLICA STATUS\G

-- 遅延やエラーの監視項目を定義して運用する

まとめ & 次のステップ

  • レプリケーションの基本はPrimary(書き込み)とReplica(読み取り)の役割分担
  • まずはPrimary-Replica構成の読み取り分離から理解し、段階的に拡張を検討する
  • SHOW REPLICA STATUS\G でレプリカ遅延(Seconds_Behind_Source)を定期的に監視する
  • 書き込み直後の読み取りはPrimaryから行い、Replica遅延によるデータ不整合を防ぐ
  • フェイルオーバー手順は事前に文書化し、障害時に慌てず対応できる状態にしておく

次回は 本番運用チェックリスト(MySQL版) を学びます。MySQL本番環境で確認すべき設定・監視・バックアップの観点をまとめて整理します。

The post 第29回: レプリケーションの基礎 — 単一DB構成の限界に備える読み取り分散設計 first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第28回: スロークエリログの活用 — 「なんとなく遅い」を計測ベースで解決する https://phpl4b.com/482/?utm_source=rss&utm_medium=rss&utm_campaign=28_%25e3%2582%25b9%25e3%2583%25ad%25e3%2583%25bc%25e3%2582%25af%25e3%2582%25a8%25e3%2583%25aa%25e3%2583%25ad%25e3%2582%25b0%25e3%2581%25ae%25e6%25b4%25bb%25e7%2594%25a8 Thu, 23 Apr 2026 00:00:00 +0000 https://phpl4b.com/482/ 本番でパフォーマンス問題が発生したとき、「たぶんこのクエリが重いはず」という勘で対応しても、インデックスを追加したのに改善しない・別のクエリが原因だったという事態になりがちです。

The post 第28回: スロークエリログの活用 — 「なんとなく遅い」を計測ベースで解決する first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第28回: スロークエリログの活用 — 「なんとなく遅い」を計測ベースで解決する

章: 第6章: セキュリティと本番運用

「重いクエリがある気がする」という勘に頼っていませんか?

本番でパフォーマンス問題が発生したとき、「たぶんこのクエリが重いはず」という勘で対応しても、インデックスを追加したのに改善しない・別のクエリが原因だったという事態になりがちです。

スロークエリログを有効にすると、実際に時間がかかっているクエリを記録し、改善対象を優先順位付きで把握できます。 勘ではなく証拠ベースで最適化を進めるための出発点です。

スロークエリログの主要設定と使い分け

設定項目 用途 推奨値(目安)
slow_query_log ログ有効・無効の切り替え ON
long_query_time 記録する閾値(秒) 最初は 0.51.0 秒で開始
slow_query_log_file ログの出力先パス /var/log/mysql/slow.log など
log_queries_not_using_indexes インデックス未使用クエリも記録 ON(開発時)
min_examined_row_limit 調査行数が少ないクエリを除外 状況に応じて設定

チェックポイント: long_query_time は最初は低め(0.5秒程度)に設定して観測を始めてください。閾値を高くしすぎると問題のあるクエリが記録されずに見逃します。ログが増えすぎる場合は徐々に閾値を上げて調整します。また、mysqldumpslow コマンドでログを集計すると改善優先度が見えやすくなります。

実際のコードサンプル


-- 主要設定の確認
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';

-- 実運用では設定ファイルで有効化

まとめ & 次のステップ

  • スロークエリログを有効にし、実際のボトルネックを計測ベースで特定する
  • long_query_time は低め(0.5〜1秒)から始め、記録量を見ながら調整する
  • 記録されたクエリは EXPLAIN で実行計画を確認し、フルスキャンの有無をチェックする
  • mysqldumpslow -s t slow.log で実行時間の合計が多いクエリから優先的に対応する
  • 改善前後の実行時間を必ず記録し、効果を数値で残す

次回は レプリケーションの基礎 を学びます。読み取り分散と可用性向上のためのPrimary-Replica構成の仕組みを解説します。

The post 第28回: スロークエリログの活用 — 「なんとなく遅い」を計測ベースで解決する first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第27回: SQLインジェクション対策 — 文字列連結でSQLを作っていませんか? https://phpl4b.com/480/?utm_source=rss&utm_medium=rss&utm_campaign=27_sql%25e3%2582%25a4%25e3%2583%25b3%25e3%2582%25b8%25e3%2582%25a7%25e3%2582%25af%25e3%2582%25b7%25e3%2583%25a7%25e3%2583%25b3%25e5%25af%25be%25e7%25ad%2596 Wed, 22 Apr 2026 00:00:00 +0000 https://phpl4b.com/480/ "SELECT FROM users WHERE email = '" . $email . "'" のようにPHPで文字列連結してSQLを組み立てると、' OR '1'='1 といった入力を受けたとき全データが返る脆弱性になります。これがSQLインジェクション攻撃で、OWASP...

The post 第27回: SQLインジェクション対策 — 文字列連結でSQLを作っていませんか? first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第27回: SQLインジェクション対策 — 文字列連結でSQLを作っていませんか?

章: 第6章: セキュリティと本番運用

ユーザーの入力値をそのままSQLに埋め込んでいませんか?

"SELECT * FROM users WHERE email = '" . $email . "'" のようにPHPで文字列連結してSQLを組み立てると、' OR '1'='1 といった入力を受けたとき全データが返る脆弱性になります。これがSQLインジェクション攻撃で、OWASP Top 10に毎回ランクインする重大リスクです。

根本的な対策はただ一つ:プリペアドステートメント(プレースホルダ)を使い、SQL文と値を分離して渡すことです。

危険な書き方と安全な書き方の比較

方法 リスク 推奨度
文字列連結でSQL生成 SQLインジェクション攻撃に脆弱 使用禁止
addslashes などでエスケープ 抜け穴が存在し不完全 非推奨
プリペアドステートメント(PDO) SQL文と値が完全分離され安全 推奨
ORMのクエリビルダ経由 内部でプレースホルダを使用 推奨
生のクエリをORM経由でrawSQL 文字列連結と同様のリスクあり 要注意

チェックポイント: ORMを使っていても whereRaw()DB::statement() に変数を文字列連結で渡すとSQLインジェクションが発生します。rawメソッドには必ずバインディング引数を使ってください。

実際のコードサンプル


-- NG: 文字列連結でSQL生成
-- SELECT * FROM users WHERE email = '" + email + "';

-- OK: プレースホルダ
PREPARE stmt FROM 'SELECT * FROM users WHERE email = ?';
SET @email = 'yuki@example.com';
EXECUTE stmt USING @email;
DEALLOCATE PREPARE stmt;

まとめ & 次のステップ

  • SQL文とユーザー入力値は必ず分離し、プレースホルダ経由でバインドする
  • PHPでは PDO のプリペアドステートメントを使い、文字列連結によるSQL生成を完全に禁止する
  • ORMを使う場合も whereRaw() などの生SQLには必ずバインディング引数を渡す
  • コードレビューで「変数をSQLに直接埋め込んでいる箇所がないか」を確認するルールを設ける
  • WAF(Webアプリケーションファイアウォール)は補完策であり、プレースホルダの代替にはならない

次回は スロークエリログの活用 を学びます。勘に頼らず計測ベースでクエリを改善する方法を解説します。

The post 第27回: SQLインジェクション対策 — 文字列連結でSQLを作っていませんか? first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第26回: 権限管理の基本(GRANT) — rootを共用し続けると何が起きるか https://phpl4b.com/478/?utm_source=rss&utm_medium=rss&utm_campaign=26_%25e6%25a8%25a9%25e9%2599%2590%25e7%25ae%25a1%25e7%2590%2586%25e3%2581%25ae%25e5%259f%25ba%25e6%259c%25acgrant Tue, 21 Apr 2026 00:00:00 +0000 https://phpl4b.com/478/ 開発環境の便利さそのままに、本番でも root ユーザーをアプリに使わせているケースがあります。この状態では、SQLインジェクション攻撃を受けた場合やアプリのバグでDROPが実行された場合に、データベース全体が被害を受けるリスクがあります。

The post 第26回: 権限管理の基本(GRANT) — rootを共用し続けると何が起きるか first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第26回: 権限管理の基本(GRANT) — rootを共用し続けると何が起きるか

章: 第6章: セキュリティと本番運用

本番DBにアプリが root で接続していませんか?

開発環境の便利さそのままに、本番でも root ユーザーをアプリに使わせているケースがあります。この状態では、SQLインジェクション攻撃を受けた場合やアプリのバグでDROPが実行された場合に、データベース全体が被害を受けるリスクがあります。

最小権限の原則(Principle of Least Privilege) に従い、アプリに必要な操作だけを許可した専用ユーザーを作ることが、セキュリティ強化の第一歩です。

権限設計の比較:rootと最小権限ユーザー

観点 root共用 専用ユーザー(最小権限)
影響範囲 全データベース・全テーブル 対象DBのみ
事故時のリスク DROP TABLE・DROP DATABASEまで実行可能 許可した操作のみ
環境ごとの分離 不可(全環境同一) 本番・ステージング・開発で別ユーザー設定が可能
監査ログの活用 誰が何をしたか不明 ユーザーごとに操作を追跡しやすい
推奨度 非推奨(本番では使用しない) 推奨

チェックポイント: アプリユーザーに GRANT ALL PRIVILEGES を付与するのは root と同義です。SELECT, INSERT, UPDATE, DELETE の4つから始め、必要になった権限だけを追加する方針を取ってください。また、パスワードは強固な値を使い、.env ファイルで管理してリポジトリに含めないことを徹底してください。

実際のコードサンプル


CREATE USER 'app_user'@'%' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON blog_app.* TO 'app_user'@'%';
FLUSH PRIVILEGES;

まとめ & 次のステップ

  • 本番アプリには専用DBユーザーを作成し、rootの共用を廃止する
  • GRANT は必要最小限の操作のみ付与し、GRANT ALL は避ける
  • 環境(本番・ステージング・開発)ごとにユーザーを分離する
  • SHOW GRANTS FOR 'ユーザー名'@'ホスト'; で現在の権限を定期的に確認する
  • パスワードはランダムな強固な値を使い、バージョン管理に含めない

次回は SQLインジェクション対策 を学びます。文字列連結でSQLを組み立てる危険性と、プリペアドステートメントによる根本的な防御方法を解説します。

The post 第26回: 権限管理の基本(GRANT) — rootを共用し続けると何が起きるか first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第25回: ビューとストアドプロシージャ — 共通SQLをDB側で管理する判断基準 https://phpl4b.com/476/?utm_source=rss&utm_medium=rss&utm_campaign=25_%25e3%2583%2593%25e3%2583%25a5%25e3%2583%25bc%25e3%2581%25a8%25e3%2582%25b9%25e3%2583%2588%25e3%2582%25a2%25e3%2583%2589%25e3%2583%2597%25e3%2583%25ad%25e3%2582%25b7%25e3%2583%25bc%25e3%2582%25b8%25e3%2583%25a3 Mon, 20 Apr 2026 00:00:00 +0000 https://phpl4b.com/476/ 「論理削除を除いた有効ユーザーを取得するSQL」や「集計結果を求めるSQL」が、コントローラー・バッチ・APIエンドポイントにそれぞれコピーされている状態は管理が困難です。1箇所の条件変更が漏れると、データの不整合を引き起こします。

The post 第25回: ビューとストアドプロシージャ — 共通SQLをDB側で管理する判断基準 first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第25回: ビューとストアドプロシージャ — 共通SQLをDB側で管理する判断基準

章: 第5章: 設計品質を上げる

同じSQLをアプリの複数箇所にコピーしていませんか?

「論理削除を除いた有効ユーザーを取得するSQL」や「集計結果を求めるSQL」が、コントローラー・バッチ・APIエンドポイントにそれぞれコピーされている状態は管理が困難です。1箇所の条件変更が漏れると、データの不整合を引き起こします。

ビューとストアドプロシージャを使うと、共通SQLをDB側に1箇所集約でき、アプリコードをシンプルに保てます。 ただし、万能ではないため使いどころを正しく判断することが重要です。

ビューとストアドプロシージャの使い分け

機能 ビュー(VIEW) ストアドプロシージャ(Stored Procedure)
主な用途 参照クエリの再利用・カラムの隠蔽 複数SQLをまとめた手続きの再利用
引数の受け渡し 不可 可能
トランザクション制御 不可 可能
デバッグのしやすさ 容易 やや難しい
向いているケース 読み取り専用の集約・フィルタリング バッチ処理・複数テーブル更新のまとめ
注意点 複雑なビューはパフォーマンスが低下しやすい ロジックがDB側に分散してバージョン管理が難しくなる

チェックポイント: ストアドプロシージャはビジネスロジックをDBに持ち込みすぎると、アプリとDBの責務が混在してメンテナンスが困難になります。まずはビューから導入し、手続き的な処理が必要になった場合にのみストアドプロシージャを検討してください。

実際のコードサンプル


CREATE VIEW v_active_users AS
SELECT id, name, email
FROM users
WHERE deleted_at IS NULL;

SELECT * FROM v_active_users LIMIT 10;

まとめ & 次のステップ

  • まずは読み取り専用のビューから導入し、共通SQLを1箇所に集約する
  • ビューは deleted_at IS NULL のような共通フィルターを隠蔽するのに特に有効
  • ストアドプロシージャは複数SQL・トランザクション制御が必要な場面に限定して使う
  • ビューのSQLが複雑になりすぎた場合は、アプリ側のRepository層に戻すことも選択肢に入れる
  • どちらも変更時はアプリへの影響範囲を確認してからDDLを実行する

次回は 権限管理の基本(GRANT) を学びます。最小権限の原則でDBユーザーを設計し、セキュリティを強化する方法を解説します。

The post 第25回: ビューとストアドプロシージャ — 共通SQLをDB側で管理する判断基準 first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第24回: パーティションの考え方 — 巨大テーブルの運用負荷を設計で下げる https://phpl4b.com/474/?utm_source=rss&utm_medium=rss&utm_campaign=24_%25e3%2583%2591%25e3%2583%25bc%25e3%2583%2586%25e3%2582%25a3%25e3%2582%25b7%25e3%2583%25a7%25e3%2583%25b3%25e3%2581%25ae%25e8%2580%2583%25e3%2581%2588%25e6%2596%25b9 Sun, 19 Apr 2026 00:00:00 +0000 https://phpl4b.com/474/ アクセスログや履歴データを1つのテーブルに蓄積し続けると、削除クエリが重くなり、バックアップに時間がかかり、インデックスが肥大化する問題が起きます。DELETE WHERE accessedat < '2024-01-01' を流すだけで数十分かかる、というケースも珍しくありませ...

The post 第24回: パーティションの考え方 — 巨大テーブルの運用負荷を設計で下げる first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第24回: パーティションの考え方 — 巨大テーブルの運用負荷を設計で下げる

章: 第5章: 設計品質を上げる

ログテーブルが数千万件を超えたとき、どう対処しますか?

アクセスログや履歴データを1つのテーブルに蓄積し続けると、削除クエリが重くなり、バックアップに時間がかかり、インデックスが肥大化する問題が起きます。DELETE WHERE accessed_at < '2024-01-01' を流すだけで数十分かかる、というケースも珍しくありません。

MySQLのパーティションを活用すると、月ごと・年ごとにデータを物理的に分割でき、期間削除を ALTER TABLE ... DROP PARTITION の一瞬で完了させることができます。

パーティションの種類と使いどころ

パーティション種別 分割キー 向いているケース
RANGE 値の範囲(日付・IDなど) 月次ログ・期間削除が必要なデータ
LIST 指定した値のリスト 地域コード・カテゴリなど固定値での分割
HASH ハッシュ値で均等分散 均等なI/O分散が目的の場合
KEY MySQL内部キーで均等分散 主キーによる均等分割

実務での第一候補は RANGE パーティション(日付キー) です。期間削除と検索の両方に効果があります。

チェックポイント: パーティションは「全テーブルに適用すべき万能手段」ではありません。WHERE句にパーティションキーが含まれない検索では全パーティションを走査するため、むしろ遅くなることがあります。適用前に EXPLAIN PARTITIONS で動作を確認してください。

実際のコードサンプル


CREATE TABLE access_logs (
  id BIGINT UNSIGNED NOT NULL,
  accessed_at DATETIME NOT NULL,
  user_id BIGINT UNSIGNED,
  PRIMARY KEY (id, accessed_at)
)
PARTITION BY RANGE (TO_DAYS(accessed_at)) (
  PARTITION p202604 VALUES LESS THAN (TO_DAYS('2026-05-01')),
  PARTITION p202605 VALUES LESS THAN (TO_DAYS('2026-06-01'))
);

まとめ & 次のステップ

  • パーティションは「期間削除が頻繁」「検索範囲が明確」なテーブルに限定して検討する
  • まずは月次ログなど適用条件が明確なテーブルから始める
  • DROP PARTITION による高速削除はパーティションの最大のメリットなので積極的に活用する
  • WHERE句にパーティションキーを含めないと効果がないため、クエリパターンを先に確認する
  • 既存テーブルへの後付けは ALTER TABLE ... PARTITION BY で可能だが、大量データの場合はロック時間に注意する

次回は ビューとストアドプロシージャ を学びます。共通SQLをDB側で管理する方法と、その使い分けの判断基準を解説します。

The post 第24回: パーティションの考え方 — 巨大テーブルの運用負荷を設計で下げる first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第23回: 正規化と非正規化の判断 — 「常に正規化」が正解とは限らない理由 https://phpl4b.com/472/?utm_source=rss&utm_medium=rss&utm_campaign=23_%25e6%25ad%25a3%25e8%25a6%258f%25e5%258c%2596%25e3%2581%25a8%25e9%259d%259e%25e6%25ad%25a3%25e8%25a6%258f%25e5%258c%2596%25e3%2581%25ae%25e5%2588%25a4%25e6%2596%25ad Sat, 18 Apr 2026 00:00:00 +0000 https://phpl4b.com/472/ 「とにかく正規化すれば正しい」と思っていると、複雑なJOINが増えてパフォーマンスが劣化したり、集計クエリが毎回重くなったりする問題に直面します。一方で「非正規化でいいや」と安易に判断すると、データの更新異常や整合性の崩壊を招きます。

The post 第23回: 正規化と非正規化の判断 — 「常に正規化」が正解とは限らない理由 first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第23回: 正規化と非正規化の判断 — 「常に正規化」が正解とは限らない理由

章: 第5章: 設計品質を上げる

テーブル設計で「正規化すべきか、しないべきか」に迷ったことはありませんか?

「とにかく正規化すれば正しい」と思っていると、複雑なJOINが増えてパフォーマンスが劣化したり、集計クエリが毎回重くなったりする問題に直面します。一方で「非正規化でいいや」と安易に判断すると、データの更新異常や整合性の崩壊を招きます。

正規化と非正規化は「保守性」と「性能」のトレードオフです。目的と参照特性を把握したうえで、意図的に使い分けることが設計品質の鍵です。

正規化と非正規化、どう使い分けるか?

基本方針は「まず正規化で設計し、ボトルネックが計測で確認できてから限定的に非正規化する」です。

観点 正規化 非正規化
データの整合性 高い(冗長なし) 低下リスクあり(更新が複数箇所に波及)
書き込み性能 高い 書き込み時に集計値の更新が必要
読み取り性能 JOINが増えると低下 読み取りが高速になりやすい
向いているケース マスタ系・更新頻度が高いデータ 集計・レポート・参照が圧倒的に多いデータ
典型例 ユーザー情報・注文明細 投稿数のカウント・ランキング集計

チェックポイント: 非正規化を検討する前に EXPLAIN でボトルネックを特定してください。「なんとなく遅そう」で非正規化すると、保守コストだけが増えて性能は改善されないことがあります。

実際のコードサンプル


-- 例: 集計結果を別テーブルで保持
CREATE TABLE user_stats (
  user_id BIGINT UNSIGNED PRIMARY KEY,
  post_count INT NOT NULL,
  updated_at DATETIME NOT NULL
);

まとめ & 次のステップ

  • 設計の出発点は正規化とし、データの冗長をなくす
  • 非正規化は「計測でボトルネックが確認できた」後に、限定的な範囲で行う
  • 非正規化した箇所は更新タイミングとトリガーを設計に明記しておく
  • 集計用の別テーブルを作る場合は、更新漏れを防ぐ仕組み(バッチ・イベント)とセットで考える
  • 判断理由をドキュメントに残すと、将来の見直しやレビューで役立つ

次回は パーティションの考え方 を学びます。巨大テーブルの運用負荷を下げるパーティション設計の判断基準を解説します。

The post 第23回: 正規化と非正規化の判断 — 「常に正規化」が正解とは限らない理由 first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第22回: NULL設計とデフォルト値 — 「意味のないNULL」がバグを生む前に https://phpl4b.com/470/?utm_source=rss&utm_medium=rss&utm_campaign=22_null%25e8%25a8%25ad%25e8%25a8%2588%25e3%2581%25a8%25e3%2583%2587%25e3%2583%2595%25e3%2582%25a9%25e3%2583%25ab%25e3%2583%2588%25e5%2580%25a4 Fri, 17 Apr 2026 00:00:00 +0000 https://phpl4b.com/470/ カラムに深く考えずNULLを許可した結果、アプリ側で if ($value !== null) が乱発され、仕様の解釈が人によって異なるトラブルが起きることがあります。「このNULLは未入力なのか、削除済みなのか、不明なのか?」が曖昧なまま設計が進むと、バグの温床になります。

The post 第22回: NULL設計とデフォルト値 — 「意味のないNULL」がバグを生む前に first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第22回: NULL設計とデフォルト値 — 「意味のないNULL」がバグを生む前に

章: 第5章: 設計品質を上げる

「このカラム、NULLでいいや」が後から問題になっていませんか?

カラムに深く考えずNULLを許可した結果、アプリ側で if ($value !== null) が乱発され、仕様の解釈が人によって異なるトラブルが起きることがあります。「このNULLは未入力なのか、削除済みなのか、不明なのか?」が曖昧なまま設計が進むと、バグの温床になります。

NULL設計とデフォルト値を最初に明確にしておくことが、アプリ側の分岐をシンプルに保つ最短ルートです。

NULLを許可する基準を決める

NULLを許可するかどうかは、「そのカラムに値が存在しない状態が業務上ありうるか」で判断します。迷ったときは次の比較表を参考にしてください。

カラムの性質 NULL許可 推奨設計
必ず値が入るべき項目(名前・メールなど) NG NOT NULL + バリデーションで保証
任意入力項目(自己紹介文など) OK NULL を「未設定」の意味で使う
フラグや状態(公開・非公開など) NG NOT NULL DEFAULT 0 などデフォルト値を設定
外部キー(任意の関連) OK NULL を「関連なし」の意味で使う
削除日時(論理削除) OK NULL = 未削除、値あり = 削除済み

チェックポイント: テーブル設計レビュー時に「このNULLは何を意味するか、1行で説明できますか?」と問いかけてみてください。説明できないNULLは設計の見直しサインです。

実際のコードサンプル


CREATE TABLE profiles (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT UNSIGNED NOT NULL,
  bio TEXT NULL,
  is_public TINYINT(1) NOT NULL DEFAULT 0
);

まとめ & 次のステップ

  • NULLを許可するカラムには「このNULLが意味すること」をコメントやドキュメントに残す
  • フラグや状態値は NOT NULL DEFAULT を使い、NULLを混入させない
  • 任意入力項目は NULL 許可で「未入力」を表現し、空文字との混在を避ける
  • 既存テーブルのNULL設計を見直すときは SHOW FULL COLUMNS FROM テーブル名; から現状把握を始める
  • 設計段階で「NULLを許可する理由を列ごとに1行で言える」状態を目標にする

次回は 正規化と非正規化の判断 を学びます。常に正規化が正解とは限らない理由と、パフォーマンスとのバランスを取る判断基準を解説します。

The post 第22回: NULL設計とデフォルト値 — 「意味のないNULL」がバグを生む前に first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第21回: 文字コードと照合順序 — 文字化けを根本から防ぐ統一戦略 https://phpl4b.com/468/?utm_source=rss&utm_medium=rss&utm_campaign=21_%25e6%2596%2587%25e5%25ad%2597%25e3%2582%25b3%25e3%2583%25bc%25e3%2583%2589%25e3%2581%25a8%25e7%2585%25a7%25e5%2590%2588%25e9%25a0%2586%25e5%25ba%258f Thu, 16 Apr 2026 00:00:00 +0000 https://phpl4b.com/468/ 日本語を扱うアプリを作っていると、突然文字化けが発生したり、大文字・小文字の比較が意図通りに動かなかったりする場面があります。原因は多くの場合、文字コードと照合順序の設定が統一されていないことにあります。

The post 第21回: 文字コードと照合順序 — 文字化けを根本から防ぐ統一戦略 first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>
第21回: 文字コードと照合順序 — 文字化けを根本から防ぐ統一戦略

章: 第5章: 設計品質を上げる

「なぜ文字化けが直らないのか?」と悩んでいませんか?

日本語を扱うアプリを作っていると、突然文字化けが発生したり、大文字・小文字の比較が意図通りに動かなかったりする場面があります。原因は多くの場合、文字コードと照合順序の設定が統一されていないことにあります。

後から修正しようとすると、既存データの変換・アプリ側の修正・テストをすべてやり直す必要が出てきます。設計の最初に正しく統一しておくことが、最も低コストな解決策です。

文字コードと照合順序とは何か?

文字コード(CHARACTER SET) は「どの文字を扱えるか」を決める規則です。MySQLで日本語を安全に扱うには utf8mb4 が必須です(utf8 は絵文字に対応していないため不十分です)。

照合順序(COLLATION) は「文字をどう比較・並び替えるか」を決める規則です。utf8mb4_unicode_ci は大文字・小文字を区別しない比較を行います。

両者がデータベース・テーブル・カラム・接続の各レベルで一致していないと、文字化けや比較不整合が発生します。

設定レベル 確認コマンド 推奨値
データベース SHOW CREATE DATABASE db名; utf8mb4 / utf8mb4_unicode_ci
テーブル SHOW CREATE TABLE テーブル名; utf8mb4 / utf8mb4_unicode_ci
カラム SHOW FULL COLUMNS FROM テーブル名; utf8mb4 / utf8mb4_unicode_ci
接続 SHOW VARIABLES LIKE 'character_set_%'; utf8mb4

チェックポイント: utf8utf8mb4 は別物です。日本語サービスでは必ず utf8mb4 に統一し、SHOW FULL COLUMNS FROM テーブル名; で各カラムの照合順序が揃っているかを確認してください。

実際のコードサンプル


SHOW CREATE DATABASE blog_app;
SHOW FULL COLUMNS FROM users;

ALTER TABLE users
  CONVERT TO CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

まとめ & 次のステップ

  • utf8mb4 + utf8mb4_unicode_ci をプロジェクト開始時に全レベルで統一する
  • SHOW FULL COLUMNS FROM テーブル名; で現状の設定を必ず確認する
  • 既存テーブルの変換は CONVERT TO CHARACTER SET で行い、変換後はデータを目視確認する
  • 接続文字コードもアプリ側(DSN や SET NAMES)で合わせることを忘れない
  • 設計段階でルールをドキュメントに残すと、チーム全体での一貫性が保ちやすくなる

次回は NULL設計とデフォルト値 を学びます。「NULLを許可すべきか」の判断基準を整理し、アプリ側の分岐をシンプルに保つ設計術を解説します。

The post 第21回: 文字コードと照合順序 — 文字化けを根本から防ぐ統一戦略 first appeared on 未経験から実務レベルへ|PHP初心者向け実践学習ブログ.

]]>