RPGのセーブデータはどう保存されている?MySQLで学ぶデータベース入門

こんにちは、「ぷろぐらの森」です🌱

「ゲームを作ったけど、リロードしたらスコアが消えてしまった…」

そんな経験はありませんか?

本物のRPGゲームはセーブデータが消えませんよね。それはデータベース(DB)という仕組みのおかげです!

この記事では、RPGのセーブデータを例にしながら、MySQLの基本的な考え方・テーブル設計・実際のSQL構文をやさしく解説します!

目次

この記事でわかること

  • データベース(MySQL)がなぜ必要なのか
  • テーブル設計の基本(悪い例 vs 良い例)
  • CREATE TABLEでテーブルを実際に作る方法
  • データ型の正しい選び方(インデックスの現場裏話付き)
  • 現場でよくある失敗パターン3選

電源を切ったらデータが消える!?ゲームの保存問題

JavaScriptで作ったゲームを動かしていたら、ブラウザをリロードした瞬間にスコアが0に戻った経験はありませんか?

// ブラウザのメモリにしか保存されていない
let score = 0;
let playerName = "ゆうしゃ";

これはデータがブラウザのメモリ(一時記憶)に入っているだけだから。電源を切ると全部消えてしまいます!

本物のRPGゲームのセーブデータが消えないのは、データベース(DB)というしくみを使ってサーバー側にデータを保存しているからです!

データベースとは「賢い電子台帳」

データベースを一言で言うなら、「高性能な電子台帳」です。

Excelで想像してみましょう。縦に行が並び、横に列が並ぶシートがありますよね?データベースのテーブルはそれとよく似ています。

idnamelevelscore
1ゆうしゃ1548200
2まほうつかい812000

ただし、Excelとは違って次の点が優れています!

  • 大量のデータを高速に検索できる(100万件でも一瞬)
  • 複数人が同時にアクセスできる(オンラインゲームはこれが必須)
  • データの整合性を守ってくれる(おかしなデータが入らないよう防いでくれる)

MySQLは、そんなデータベースを管理するソフトウェアの中でも世界で最もよく使われているもののひとつです!

実際に設計してみよう!「勇者のセーブデータ」を保存する

❌ 悪い例:なんでも詰め込みすぎ

最初にやりがちな失敗がこれです。

iddata
1ゆうしゃ,15,100,48200,2026-04-01

1つのマスにカンマ区切りで全部詰め込んでいます。一見うまくやっている気がしますが…

  • 「レベルだけ検索したい」ときにとても不便
  • レベルだけ10に更新するのが難しい
  • データが増えると破綻する

⭕ 良い例:項目ごとに列(カラム)を分ける

idnamelevelhpscoresaved_at
1ゆうしゃ15100482002026-04-01

カラムを分けると「レベルだけ更新する」「スコア順に並べる」がとても簡単になります!

テーブルを実際に作ってみよう!

良い設計のテーブルを作るSQLがこちらです。

CREATE TABLE users (
  id       INT          AUTO_INCREMENT PRIMARY KEY,
  name     VARCHAR(50)  NOT NULL,
  level    INT          DEFAULT 1,
  hp       INT          DEFAULT 100,
  score    INT          DEFAULT 0,
  saved_at DATETIME     DEFAULT CURRENT_TIMESTAMP
);

このSQLは、MySQLのコマンドライン・phpMyAdmin・TablePlusなど、
お使いのMySQLクライアントで実行できます!

各キーワードの意味はこちらです。

キーワード意味
INT整数(レベル・HP・スコアなど)
VARCHAR(50)最大50文字の文字列(プレイヤー名など)
DATETIME日時(セーブした時刻)
NOT NULL空っぽを許可しない
DEFAULT 1値がなければ自動的に1を入れる
AUTO_INCREMENT PRIMARY KEY自動で連番を振る(IDとして使う)

【エンジニアの視点】データ型を正しく選ぶと何が変わる?

MySQLでは、カラムごとに「どんな種類のデータを入れるか」を最初に決めます。これを「型(かた)」と言います。

よく使う3つの型を覚えましょう!

意味ゲームでの例
INT整数レベル・HP・スコア・所持金
VARCHAR(n)文字列(最大n文字)プレイヤー名・職業名
DATETIME日時セーブした日時
カラさん

ここだけの話をします。
現場に入ると「インデックス貼って!」とよく言われます。

インデックスとは、データを素早く見つけるための目次のようなもの。
100万人のユーザーからid = 12345の人を探すとき、インデックスがないと全員をひとりひとり確認しなければなりません。インデックスがあると、目次を見て一瞬で見つけられます。

実際に私が現場で経験した案件では、インデックスを貼り忘れたテーブルへのクエリが原因で、本番環境でタイムアウトエラーが多発したことがありました。新人のうちは「PRIMARY KEYを設定すると自動でインデックスになる」と覚えておくだけで十分です!

さきほどのCREATE TABLEAUTO_INCREMENT PRIMARY KEYを付けましたよね。
あれが基本的なインデックスです。入門のうちはこれだけ意識すればOKです!

よくある失敗パターン3選

失敗①:スコアをVARCHARで保存してしまう!

-- ❌ 間違い:スコアをVARCHARで保存
score VARCHAR(20)

こうすると、ソート結果がおかしくなります。文字列は「9」>「10」という並び順になるため、スコアランキングがめちゃくちゃに!

-- ⭕ 正しい:数値はINTで保存
score INT DEFAULT 0

数値は必ずINTで保存しましょう!

失敗②:NULL(空っぽ)を許可しすぎる!

-- ❌ 間違い:名前なしのデータが入れてしまう
name VARCHAR(50)

-- ⭕ 正しい:名前なしのデータを弾いてくれる
name VARCHAR(50) NOT NULL

プレイヤー名が空っぽのセーブデータはバグのもと。NOT NULLでデータの品質を守りましょう!

失敗③:VARCHAR(255)でなんでも保存しようとする!

「長さがわからないからとりあえず255に」はよくある罠です。適切なサイズを設定することで、データベースのパフォーマンスが上がり、おかしなデータも防げます。

プレイヤー名ならVARCHAR(50)、職業名ならVARCHAR(30)など、実際の用途に合ったサイズにしましょう!

まとめ

今日学んだことを整理しましょう!

  • データベース(MySQL)は、大量データを高速に扱える「賢い電子台帳」
  • テーブル設計は「1カラム1データ」が基本
  • 型(INT / VARCHAR / DATETIME)を正しく選ぶことでバグを防げる
  • CREATE TABLENOT NULLDEFAULTを活用しよう
  • インデックスは「目次」。PRIMARY KEYが基本のインデックスになる

次のステップは「実際にデータを追加・検索・更新・削除する」SQL操作(INSERT / SELECT / UPDATE / DELETE)です。次の記事で実際に動かしてみましょう!

次の記事を読む!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

神奈川県出身
どこにでもいる現役ゲーム会社サーバーエンジニア。大学ではひたすらゲーム!ゲーム!という人生を送ってました。

このブログは「ゲームを作ってみたい!」「プログラミングに関する知識をつけたい!」そんな皆さんの少しでもお役になれば嬉しいなと思い開設しました。

趣味
YouTube鑑賞、ストリートな格闘ゲーム、キャンプ

最近の出来事
・痔主になってしまいました....
・Google Cloud Professional Cloud Architect取得しました。

コメント

コメントする

目次