STEP 18:プロジェクト① SNS設計【中級】

🚀 STEP 18: プロジェクト① SNS設計【中級】

Twitter風SNSのデータベースを設計してみよう

📋 このステップで学ぶこと
  • SNSシステムの要件分析
  • ER図の作成(ユーザー、投稿、フォロー、いいね、コメント)
  • 多対多リレーションの処理方法
  • 正規化の適用
  • インデックス設計戦略
  • パフォーマンスを考慮したテーブル設計

学習時間の目安: 3時間 | 難易度: 中級

📋 1. プロジェクト概要

STEP 17からの続き:総合プロジェクトへ

STEP 17まででMongoDBの実践を学びました。このSTEP 18からは、これまで学んだ全ての知識を活用して、実際のシステム設計プロジェクトに挑戦します。最初のプロジェクトはTwitter風SNSのデータベース設計です。ユーザー管理、投稿、フォロー、いいねなど、SNSの核となる機能を設計しましょう。

システム要件

🎯 作成するSNSの機能
  • ユーザー管理:登録、プロフィール編集、認証
  • 投稿機能:テキスト投稿、画像添付
  • フォロー機能:ユーザー同士のフォロー・フォロワー
  • いいね機能:投稿へのいいね
  • コメント機能:投稿へのコメント
  • タイムライン:フォロー中のユーザーの投稿表示
  • ハッシュタグ:投稿にタグ付け、検索

エンティティの洗い出し

まず、システムに必要なエンティティ(実体)を洗い出します。

エンティティ 説明 主な属性
users(ユーザー) SNSの利用者 ID、ユーザー名、メール、パスワード、プロフィール
posts(投稿) ユーザーが投稿する内容 ID、本文、画像URL、投稿日時、ユーザーID
follows(フォロー関係) 誰が誰をフォローしているか フォローする人ID、フォローされる人ID
likes(いいね) 投稿へのいいね ユーザーID、投稿ID、日時
comments(コメント) 投稿へのコメント ID、本文、投稿ID、ユーザーID、日時
hashtags(ハッシュタグ) タグ情報 ID、タグ名
post_hashtags(投稿-タグ関連) 投稿とタグの関係 投稿ID、ハッシュタグID

リレーションシップの整理

【1対多の関係】 users → posts(1人のユーザーが複数の投稿) users → comments(1人のユーザーが複数のコメント) posts → comments(1つの投稿に複数のコメント) 【多対多の関係】 users ⇔ users(フォロー関係:相互にフォロー可能) users ⇔ posts(いいね:多数のユーザーが多数の投稿にいいね) posts ⇔ hashtags(1つの投稿に複数タグ、1つのタグが複数投稿に使用)

📐 2. ER図の作成

ER図(概念図)

┌─────────────────┐ │ users │ ├─────────────────┤ │ user_id (PK) │ │ username │ │ email │ │ password_hash │ │ display_name │ │ bio │ │ avatar_url │ │ created_at │ └─────────────────┘ │1 │ │* ┌─────────────────┐ ┌─────────────────┐ │ posts │ │ post_hashtags │ ├─────────────────┤ ├─────────────────┤ │ post_id (PK) │────*│ post_id (FK) │ │ user_id (FK) │ │ hashtag_id (FK) │ │ content │ └─────────────────┘ │ image_url │ │ │ created_at │ │* └─────────────────┘ │1 │1 │ │ ┌─────────────────┐ │* │ hashtags │ ┌─────────────────┐ ├─────────────────┤ │ comments │ │ hashtag_id (PK) │ ├─────────────────┤ │ tag_name │ │ comment_id (PK) │ │ created_at │ │ post_id (FK) │ └─────────────────┘ │ user_id (FK) │ │ content │ │ created_at │ └─────────────────┘ ┌─────────────────┐ ┌─────────────────┐ │ likes │ │ follows │ ├─────────────────┤ ├─────────────────┤ │ user_id (FK) │ │ follower_id(FK) │ │ post_id (FK) │ │ following_id(FK)│ │ created_at │ │ created_at │ └─────────────────┘ └─────────────────┘
💡 ER図のポイント
  • PK(主キー):テーブル内で一意に識別する
  • FK(外部キー):他のテーブルを参照する
  • 1:1件のレコード
  • *:複数件のレコード(多)

🗄️ 3. テーブル設計(DDL)

usersテーブル

CREATE TABLE users ( — 主キー:BIGINTで大規模SNSにも対応 user_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, — ユーザー名:@yamadaのような一意のID username VARCHAR(50) NOT NULL UNIQUE, — メールアドレス:ログイン認証に使用 email VARCHAR(255) NOT NULL UNIQUE, — パスワード:必ずハッシュ化して保存(平文は絶対NG) password_hash VARCHAR(255) NOT NULL, — 表示名:プロフィールに表示される名前 display_name VARCHAR(100) NOT NULL, — 自己紹介:長文対応でTEXT型 bio TEXT, — プロフィール画像のURL avatar_url VARCHAR(500), — 作成日時・更新日時:自動設定 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, — インデックス:検索で使うカラムに設定 INDEX idx_username (username), INDEX idx_email (email) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
🎯 設計のポイント
  • username:UNIQUE制約で重複を防ぐ
  • password_hash:パスワードは必ずハッシュ化して保存
  • bio:TEXT型(長い自己紹介に対応)
  • インデックス:検索に使うカラムに設定

postsテーブル

CREATE TABLE posts ( — 主キー:投稿の一意識別子 post_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, — 投稿者のID:usersテーブルへの外部キー user_id BIGINT UNSIGNED NOT NULL, — 投稿内容:TEXT型で長文にも対応 content TEXT NOT NULL, — 添付画像のURL(任意) image_url VARCHAR(500), — いいね数・コメント数:非正規化(毎回COUNTするより高速) likes_count INT UNSIGNED DEFAULT 0, comments_count INT UNSIGNED DEFAULT 0, — タイムスタンプ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, — 外部キー:ユーザー削除時に投稿も自動削除 FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE, — インデックス:タイムライン取得の高速化 INDEX idx_user_id (user_id), INDEX idx_created_at (created_at DESC) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
🎯 設計のポイント
  • likes_count, comments_count:非正規化(高速化のため)
  • ON DELETE CASCADE:ユーザー削除時に投稿も自動削除
  • idx_created_at:降順インデックス(新着順取得)

followsテーブル(多対多)

CREATE TABLE follows ( — フォローする側のユーザーID follower_id BIGINT UNSIGNED NOT NULL, — フォローされる側のユーザーID following_id BIGINT UNSIGNED NOT NULL, — フォローした日時 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, — 複合主キー:同じフォロー関係の重複を防止 PRIMARY KEY (follower_id, following_id), — 外部キー:ユーザー削除時にフォロー関係も自動削除 FOREIGN KEY (follower_id) REFERENCES users(user_id) ON DELETE CASCADE, FOREIGN KEY (following_id) REFERENCES users(user_id) ON DELETE CASCADE, — インデックス:フォロワー一覧・フォロー一覧の取得高速化 INDEX idx_follower (follower_id), INDEX idx_following (following_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
💡 複合主キーの使用

(follower_id, following_id)を複合主キーにすることで:
✅ 同じフォロー関係の重複を防げる
✅ 別途IDカラムが不要
✅ 一意性が保証される

likesテーブル(多対多)

CREATE TABLE likes ( — いいねしたユーザーのID user_id BIGINT UNSIGNED NOT NULL, — いいねされた投稿のID post_id BIGINT UNSIGNED NOT NULL, — いいねした日時 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, — 複合主キー:同じユーザーが同じ投稿に2回いいねできない PRIMARY KEY (user_id, post_id), — 外部キー:関連データ削除時に自動削除 FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE, FOREIGN KEY (post_id) REFERENCES posts(post_id) ON DELETE CASCADE, — インデックス:「この投稿にいいねした人一覧」取得用 INDEX idx_post_id (post_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

commentsテーブル

CREATE TABLE comments ( — 主キー:コメントの一意識別子 comment_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, — どの投稿へのコメントか post_id BIGINT UNSIGNED NOT NULL, — 誰がコメントしたか user_id BIGINT UNSIGNED NOT NULL, — コメント内容 content TEXT NOT NULL, — タイムスタンプ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, — 外部キー:関連データ削除時に自動削除 FOREIGN KEY (post_id) REFERENCES posts(post_id) ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE, — インデックス:投稿別・ユーザー別・日時順の取得高速化 INDEX idx_post_id (post_id), INDEX idx_user_id (user_id), INDEX idx_created_at (created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

hashtagsテーブル

CREATE TABLE hashtags ( — 主キー:ハッシュタグの一意識別子 hashtag_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, — タグ名:「#プログラミング」の「プログラミング」部分 tag_name VARCHAR(100) NOT NULL UNIQUE, — このタグが使われた投稿数(非正規化) posts_count INT UNSIGNED DEFAULT 0, — 作成日時 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, — インデックス:タグ名検索の高速化 INDEX idx_tag_name (tag_name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

post_hashtagsテーブル(多対多)

CREATE TABLE post_hashtags ( — どの投稿に post_id BIGINT UNSIGNED NOT NULL, — どのハッシュタグが付いているか hashtag_id BIGINT UNSIGNED NOT NULL, — 付けられた日時 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, — 複合主キー:同じ投稿に同じタグは1回だけ PRIMARY KEY (post_id, hashtag_id), — 外部キー:関連データ削除時に自動削除 FOREIGN KEY (post_id) REFERENCES posts(post_id) ON DELETE CASCADE, FOREIGN KEY (hashtag_id) REFERENCES hashtags(hashtag_id) ON DELETE CASCADE, — インデックス:「このタグの投稿一覧」取得用 INDEX idx_hashtag_id (hashtag_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

🔍 4. よくあるクエリとインデックス最適化

タイムライン取得(重要なクエリ)

— ユーザーID=1のタイムライン(フォロー中のユーザーの投稿) SELECT p.post_id, p.content, p.image_url, p.likes_count, p.comments_count, p.created_at, u.username, u.display_name, u.avatar_url FROM posts p INNER JOIN users u ON p.user_id = u.user_id INNER JOIN follows f ON f.following_id = p.user_id WHERE f.follower_id = 1 ORDER BY p.created_at DESC LIMIT 20;
🚀 パフォーマンス最適化

このクエリを高速化するために、以下のインデックスが必要:

  • follows(follower_id, following_id):複合主キー
  • posts(created_at DESC):降順インデックス
  • posts(user_id):外部キー

いいね数ランキング(人気投稿)

— 過去7日間で最もいいねされた投稿TOP10 SELECT p.post_id, p.content, p.likes_count, u.username, u.display_name FROM posts p INNER JOIN users u ON p.user_id = u.user_id WHERE p.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) ORDER BY p.likes_count DESC LIMIT 10;

ハッシュタグ検索

— #MongoDBタグの付いた投稿を検索 SELECT p.post_id, p.content, p.created_at, u.username FROM posts p INNER JOIN users u ON p.user_id = u.user_id INNER JOIN post_hashtags ph ON p.post_id = ph.post_id INNER JOIN hashtags h ON ph.hashtag_id = h.hashtag_id WHERE h.tag_name = ‘MongoDB’ ORDER BY p.created_at DESC LIMIT 20;
⚠️ LIKE検索の注意点

LIKE ‘%山田%’(前方一致でない)はインデックスが効かないため遅いです。
実務では全文検索エンジン(Elasticsearch等)を併用することが多いです。

🔄 5. 非正規化の戦略

なぜ非正規化するのか?

SNSでは読み取り頻度が非常に高いため、パフォーマンスを優先して一部を非正規化します。

【正規化済み(理想的だが遅い)】 postsテーブルには likes_count を持たない → いいね数を知りたいときは毎回 COUNT(*) でカウント SELECT post_id, COUNT(*) as likes_count FROM likes WHERE post_id = 123; 【非正規化(高速だが管理が必要)】 postsテーブルに likes_count カラムを追加 → いいねされるたびに +1 更新 UPDATE posts SET likes_count = likes_count + 1 WHERE post_id = 123;
カラム 正規化の観点 実務での判断
posts.likes_count likesテーブルからCOUNTすべき 非正規化OK:頻繁に読まれるため
posts.comments_count commentsテーブルからCOUNTすべき 非正規化OK:頻繁に読まれるため
users.followers_count followsテーブルからCOUNTすべき 非正規化OK:プロフィールで表示
hashtags.posts_count post_hashtagsからCOUNTすべき 非正規化OK:人気タグ表示に使用
💡 非正規化の管理方法

非正規化したカラムは、トリガーまたはアプリケーション側で常に最新に保つ必要があります。

— いいねが追加されたときのトリガー例 DELIMITER // CREATE TRIGGER after_like_insert AFTER INSERT ON likes FOR EACH ROW BEGIN UPDATE posts SET likes_count = likes_count + 1 WHERE post_id = NEW.post_id; END // DELIMITER ;

🛡️ 6. セキュリティとデータ整合性

重要な制約

【UNIQUE制約】 ✅ users.username(同じユーザー名は登録不可) ✅ users.email(同じメールアドレスは登録不可) ✅ hashtags.tag_name(同じタグ名は1つだけ) 【NOT NULL制約】 ✅ 必須項目(username, email, password_hash, content等) 【外部キー制約】 ✅ ON DELETE CASCADE(ユーザー削除時、投稿も削除) ✅ 参照整合性を保つ

プライバシーへの配慮

🔒 パスワードのハッシュ化

パスワードは絶対に平文で保存してはいけません。
bcryptArgon2を使ってハッシュ化します。

— 悪い例(絶対ダメ) INSERT INTO users (username, password) VALUES (‘yamada’, ‘password123’); — 良い例(ハッシュ化済み) INSERT INTO users (username, password_hash) VALUES (‘yamada’, ‘$2y$10$abcdefg…’);

✅ 7. セルフレビューチェックリスト

📋 設計チェックリスト

□ エンティティ設計

  • 必要なテーブルが全て洗い出されているか
  • 各テーブルの責務が明確か
  • 命名規則が統一されているか

□ 正規化

  • 第3正規形まで適用されているか
  • 非正規化する箇所は理由が明確か
  • データの重複が最小限か

□ 主キー・外部キー

  • 全テーブルに主キーが設定されているか
  • 外部キー制約が適切に設定されているか
  • ON DELETE CASCADEの使用が適切か

□ インデックス

  • 検索条件になるカラムにインデックスがあるか
  • ソートに使うカラムにインデックスがあるか
  • 外部キーにインデックスがあるか

□ セキュリティ

  • パスワードはハッシュ化されているか
  • 個人情報の扱いが適切か
  • 必要な制約(UNIQUE, NOT NULL)が設定されているか

📝 8. STEP 18 のまとめ

✅ このステップで学んだこと
  • SNSシステムの要件分析とエンティティ抽出
  • ER図の作成方法
  • 多対多リレーションの処理(中間テーブル)
  • 正規化と非正規化のバランス
  • インデックス設計によるパフォーマンス最適化
  • セキュリティとデータ整合性の考慮
💡 重要ポイント
  • SNSは読み取り頻度が高いため、パフォーマンス最適化が重要
  • 非正規化(likes_count等)は戦略的に使う
  • 多対多の関係は中間テーブル(follows, likes等)で表現
  • インデックスは検索とソートに必須
  • セキュリティ(パスワードハッシュ化等)は設計段階から考慮
🎯 次のステップへ

STEP 19では、さらに複雑なECサイトの設計に挑戦します!
在庫管理やトランザクション処理など、実務で必須の知識を学びましょう。

📝 総合演習

演習 1 応用

リツイート機能を追加してください。

要件:

  • ユーザーが他人の投稿をリツイートできる
  • 元の投稿のリツイート数をカウントする
  • タイムラインにリツイートも表示される
【解答】

1. postsテーブルにカラム追加

ALTER TABLE posts ADD COLUMN retweets_count INT UNSIGNED DEFAULT 0, ADD COLUMN original_post_id BIGINT UNSIGNED NULL, ADD FOREIGN KEY (original_post_id) REFERENCES posts(post_id) ON DELETE CASCADE;

2. リツイート作成の流れ

— 元の投稿(post_id=100)をリツイート INSERT INTO posts (user_id, content, original_post_id) VALUES (2, ”, 100); — 元の投稿のリツイート数を更新 UPDATE posts SET retweets_count = retweets_count + 1 WHERE post_id = 100;

3. タイムライン取得クエリ

SELECT p.post_id, p.content, p.original_post_id, p.created_at, u.username, op.content as original_content, ou.username as original_username FROM posts p INNER JOIN users u ON p.user_id = u.user_id LEFT JOIN posts op ON p.original_post_id = op.post_id LEFT JOIN users ou ON op.user_id = ou.user_id ORDER BY p.created_at DESC;
演習 2 発展

ダイレクトメッセージ(DM)機能を追加してください。

要件:

  • ユーザー同士が1対1でメッセージを送れる
  • 既読・未読の管理
  • メッセージ一覧を取得できる
【解答】

1. direct_messagesテーブルを作成

CREATE TABLE direct_messages ( message_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, sender_id BIGINT UNSIGNED NOT NULL, receiver_id BIGINT UNSIGNED NOT NULL, content TEXT NOT NULL, is_read BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, read_at TIMESTAMP NULL, FOREIGN KEY (sender_id) REFERENCES users(user_id) ON DELETE CASCADE, FOREIGN KEY (receiver_id) REFERENCES users(user_id) ON DELETE CASCADE, INDEX idx_sender_receiver (sender_id, receiver_id), INDEX idx_receiver_created (receiver_id, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2. メッセージ送信

INSERT INTO direct_messages (sender_id, receiver_id, content) VALUES (1, 2, ‘こんにちは!’);

3. 未読メッセージ取得

SELECT dm.message_id, dm.content, dm.created_at, u.username as sender_name FROM direct_messages dm INNER JOIN users u ON dm.sender_id = u.user_id WHERE dm.receiver_id = 2 AND dm.is_read = FALSE ORDER BY dm.created_at DESC;

4. 既読にする

UPDATE direct_messages SET is_read = TRUE, read_at = NOW() WHERE message_id = 123;
演習 3 発展

通知機能を追加してください。

要件:

  • いいね、コメント、フォローされた時に通知
  • 未読・既読の管理
  • 通知種別ごとに分類
【解答】

1. notificationsテーブルを作成

CREATE TABLE notifications ( notification_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED NOT NULL, — 通知を受け取るユーザー actor_id BIGINT UNSIGNED NOT NULL, — アクションしたユーザー notification_type ENUM(‘like’, ‘comment’, ‘follow’, ‘retweet’) NOT NULL, post_id BIGINT UNSIGNED NULL, — 関連する投稿(あれば) is_read BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE, FOREIGN KEY (actor_id) REFERENCES users(user_id) ON DELETE CASCADE, FOREIGN KEY (post_id) REFERENCES posts(post_id) ON DELETE CASCADE, INDEX idx_user_read (user_id, is_read), INDEX idx_user_created (user_id, created_at DESC) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2. 通知作成(いいね時のトリガー例)

DELIMITER // CREATE TRIGGER after_like_notification AFTER INSERT ON likes FOR EACH ROW BEGIN DECLARE post_owner_id BIGINT; SELECT user_id INTO post_owner_id FROM posts WHERE post_id = NEW.post_id; — 自分自身へのいいねは通知しない IF post_owner_id != NEW.user_id THEN INSERT INTO notifications (user_id, actor_id, notification_type, post_id) VALUES (post_owner_id, NEW.user_id, ‘like’, NEW.post_id); END IF; END // DELIMITER ;

3. 未読通知取得

SELECT n.notification_id, n.notification_type, n.created_at, u.username as actor_name, u.avatar_url as actor_avatar, p.content as post_content FROM notifications n INNER JOIN users u ON n.actor_id = u.user_id LEFT JOIN posts p ON n.post_id = p.post_id WHERE n.user_id = 1 AND n.is_read = FALSE ORDER BY n.created_at DESC LIMIT 20;

❓ よくある質問

Q1: フォロー関係のテーブルで、なぜ別途IDカラムを作らないのですか?

複合主キーで十分だからです。followsテーブルでは(follower_id, following_id)の組み合わせが一意であればよく、別途サロゲートキーを作る必要はありません。複合主キーにすることで、同じフォロー関係の重複登録を防げます。ただし、フォロー関係に追加情報(フォロー理由、ミュート設定など)を持たせたい場合は、サロゲートキーを追加することもあります。

Q2: likes_countを非正規化するとデータ不整合が起きませんか?

適切に管理しないと不整合が起きます。対策としては、トリガーを使って自動更新する方法、アプリケーション側で必ず両方更新する方法、定期的なバッチ処理で補正する方法があります。実務では、多少の誤差を許容する場合もあります(SNSのいいね数が1〜2件ずれても大きな問題にならない)。重要なのは、非正規化のメリット(パフォーマンス向上)とデメリット(管理コスト)を理解した上で判断することです。

Q3: ハッシュタグの検索が遅くならないですか?

適切なインデックス設計で高速化できます。hashtagsテーブルのtag_nameにインデックスを張り、post_hashtagsテーブルにも複合インデックスを設定することで、ハッシュタグ検索は高速に行えます。さらに大規模になった場合は、Elasticsearchなどの検索エンジンを併用することで、より高速な検索が可能になります。

Q4: タイムライン取得のクエリが複雑ですが、パフォーマンスは大丈夫ですか?

インデックスとキャッシュで対応します。フォロー数が多いユーザーのタイムライン取得は確かに重くなります。対策としては、follows(follower_id)とposts(created_at DESC)に適切なインデックスを設定する、Redisなどでタイムラインをキャッシュする、Fan-outアーキテクチャ(投稿時にフォロワーのタイムラインに事前配信)を採用するなどの方法があります。大規模SNSでは複数の手法を組み合わせています。

Q5: ON DELETE CASCADEを使うと危険ではないですか?

用途によります。ユーザー削除時に関連データも全て削除したい場合は適切です。ただし、意図せず大量のデータが削除される可能性があるため、本番環境では慎重に使う必要があります。代替手段として、論理削除(is_deletedフラグ)を使う方法や、ON DELETE SET NULLで参照をNULLにする方法もあります。重要なのは、削除の影響範囲を事前に把握しておくことです。

Q6: 投稿のコンテンツにTEXT型を使っていますが、VARCHAR(280)にすべきでは?

要件次第です。Twitterのように文字数制限を設ける場合はVARCHAR(280)が適切です。ただし、文字数制限のチェックはアプリケーション側で行うことが多く、データベース側ではTEXT型で柔軟に対応することもあります。TEXT型のデメリットは、インデックスを張る場合に長さ指定が必要なことです。実務では、要件と将来の拡張性を考慮して選択します。

📝

学習メモ

データベース設計・データモデリング - Step 18

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE