質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Oracle Database

Oracle Databaseは、米オラクルが開発・販売を行うリレーショナルデータベース管理システムです。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

5回答

1993閲覧

1人当たり1000以上の値を持つ場合のオススメなテーブル構成を知りたい

meex

総合スコア63

Oracle Database

Oracle Databaseは、米オラクルが開発・販売を行うリレーショナルデータベース管理システムです。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

8クリップ

投稿2023/01/08 14:03

実現したいこと

1ユーザ1000以上のレコードをもつ必要があるサービスを構築中です。
例えば、Twitterのフォロー/アンフォローのようなテーブル構築をしたいです。

【案①】

iduser_idfollow_user_id
159873654
259874342
359872232
:::

このようにするのが一般的だということは理解できます。

https://katakata-gym.com/blog/7lMlLHQCHBEfSseaEHuP

https://hit.hateblo.jp/entry/2016/05/09/131806
の記事を見ても、このように構築されています。

この構成だと更新や削除は簡単に行えますが、私はこれはしたくありません。
なぜなら、レコード数が膨大になるからです。

↑のようなDB構成にした場合、例えば、1000人をフォローしたら1000レコードが生成されてしまいます。
1人1000レコードx1000人=100万レコードも生成されてしまうのがネックに感じています。

【案②】
そうではなく、

iduser_idfollow_user_id
159873654,4342,2232, ...
:::

というように、1ユーザ1レコードとして、1つのカラムの中にコンマ区切りで追記していく方法を思いついています。
こうした場合、1人1レコードx1000人=1000レコードしか生成されない点を評価しています。
※なるべくレコード数を減らしたいという観点。

この案でもいいのですが、もっといい方法があるかもしれないと思い、質問させていただきました。


背景が長くなってしまいましたが、質問内容としては、

Q. Twitterのフォロワーのように、1人のユーザが1000や2000個の情報を持つ必要がある場合、1人当たりのレコード数をなるべく減らすことに重点を置いた場合、【案②】以外のやり方でいい方法はありませんでしょうか?

以上、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2023/01/08 14:19 編集

> 1人1000レコードx1000人=100万レコードも生成されてしまうのがネックに感じています。 それの何が問題なのですか? (逆に、「何が何でもレコードを減らしたい」事情はどのようなものでしょうか)
dameo

2023/01/08 18:52

構造は比較的単純だけど巨大でトランザクションも必要なデータだと、kafkaのようなソフトを使うのかなぁと漠然と思っていました。しかし、これだけ具体性のない話だけで質問しちゃうようなレベルだと、考えるだけ時間の無駄かもしれません。 まずは案1をRDBMSで作るのが正解だと思いますよ。むしろ他はなしよりのなしだと思います。あなたの自由ではありますが…
Zuishin

2023/01/08 22:07

レコードに分けた場合には効率的に検索・追加・削除できるアルゴリズムが採用されるので、まとめるものとは比較にならないほど高速になります。
otn

2023/01/09 01:51

> ※なるべくレコード数を減らしたいという観点。 高速性を犠牲にしてまでレコード数を減らすだけの意味があるのでしょうか?DBサイズの差は微々たる物だと思います。
meex

2023/01/09 08:56

>>「何が何でもレコードを減らしたい」事情はどのようなものでしょうか >>高速性を犠牲にしてまでレコード数を減らすだけの意味があるのでしょうか? レコード数が多くなるにつれて処理性能が落ちてくると聞いたので、それならなるべくレコード数を減らすようにしたいと思った次第です。 >>まずは案1をRDBMSで作るのが正解だと思いますよ。 >>まとめるものとは比較にならないほど高速になります。 回答くださった皆様のご意見をうかがう所、それがベスト...というかそれしかあり得ないのですね。理解いたしました。そもそもデータベースはそういう大量レコードになることを想定されているものだとは知りませんでした。
otn

2023/01/10 17:23

> レコード数が多くなるにつれて処理性能が落ちてくると聞いたので、 意味をちゃんと考えましょう。 同じプログラムで同じテーブル構造の場合、件数の多い方が遅くなるのは当然です。 違うプログラムで違うテーブル構造の場合、件数と速度の関係はなんとも言えません。違うプログラムなので。 DBMSが内部でうまくやってくれていることを、自分のプログラムで同じ事をコーディングすると遅くなるのが普通でしょう。
guest

回答5

0

ベストアンサー

回答

1人1000レコードx1000人=100万レコードも生成されてしまうのがネックに感じています。

何となく不安になる気持ちは分からなくは無いですが、一般的なRDBMSでは(適切に設計すれば)100万レコードくらいは処理時間的にも容量的にもネックにはなり得ません。
RDBMSというものはそのようなケースを効率的に処理するためのシステムなので、これを何となくネックになりそうのレベルで回避するべきものではありません。
(Twitter等の超大型システムで使うレベルのレコード数だとRDBMSだけだと厳しいので色んな工夫がされています)

とは言っても気になるでしょうから、
まずは、100万レコードでも1000万レコードでも作ってみて、実際に試してみるのが良いかと思いますよ。

PHP+MySQLの場合であれば以下のような形で試してみて下さい。

  • user_idにINDEXを設定する
  • 100万レコードのデータを作る(PHPでダミーデータをINSERTするか、エクセルなどでCSVを作ってphpMyAdmin CSV インポートあたりで検索してインポートする)
  • 実際に想定するSQL(例えば、ユーザーID1のフォローユーザー一覧から100IDを取得するSQL をphpMyAdminから実行してみて実行時間を確認する

SQL

1 SELCT `follow_user_id` FROM `テーブル名` WHERE `user_id` = 1 LIMIT 100;

環境にもよりますが、数ミリ~数十ミリ秒とかそういう単位の時間で処理することが出来ます。

初学者にはお勧めはしませんが別の方法

初学者には全くお勧めできませんが、
JSON型 https://dev.mysql.com/doc/refman/8.0/ja/json.html
のフィールドにJSONでデータを投入することで総レコード数がユーザー分になります。
ただ、この場合はフォローユーザー一覧は何も考えなくても高速に取得出来ますが、
その逆のフォロワー一覧を取得するのはかなり苦手になります。
それを解消しようとした場合はフォローとフォロワーを別フィールドにしてそれぞれJSON型にするなど、設計も管理も難易度が高くなります。

まずは基礎の正規化を学習して、JSON型のメリットデメリットを理解出来るようになってからの使用を強くお勧めします。

更に他の方法

RDBMS以外のデータベースを使用するのも一つの手ですが、これも初学者が学習するにはRDBMSに比べるとかなりハードルが高くなるのでお勧めできません。
単純に教材数、特に初学者向けの教材の量はRDBMSに比べると極端に少なくなります。

投稿2023/01/08 19:08

tanat

総合スコア18713

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meex

2023/01/09 09:00

詳細にたくさんの案をお教えくださりありがとうございます。 「RDBMSというものはそのようなケースを効率的に処理するためのシステムなので、これを何となくネックになりそうのレベルで回避するべきものではありません。」とのことで腑に落ちたところがありました。 データベースはそもそもそういう大量レコードになることを想定されていることを理解しました。 ちゃんと正規化されているのであれば特に問題ないのですね、丁寧にお教えくださり誠にありがとうございました。
meex

2023/01/09 09:06

皆様のご意見を頂戴したうえで検討しまして、今回は皆様の言う通り、1ユーザ複数レコードという本来のデータベースの使い方で進めようと思います。ありがとうございました。
tanat

2023/01/10 06:44

解決したようで良かったです。 > 皆様のご意見を頂戴したうえで検討しまして、今回は皆様の言う通り、1ユーザ複数レコードという本来のデータベースの使い方で進めようと思います。 はい、それが良いと思います。 その上で問題が出たら`MySQL explain 実行計画 チューニング`あたりで検索してチューニングを試みれば殆どのケースで解決すると思います。
guest

0

100万レコード程度なら気にしなくてよいと思いますが、100億とか1兆だとまた話が違ってくるので、他の案も出しておきます。

・テーブル水平分割 (例えば user_id 奇数と偶数で分ければレコード数は 2分の1になる。末尾1桁で分ければ10分の1)。ロジックが煩雑になるので分割そのものは Redshift や BigQuery 等の製品にまかせるのもアリ。
・複数サーバで分散処理。Twitter などはタイムライン表示するだけでも数百~数千(想像ですが) のサーバにリクエストを投げ、それを集約した結果を表示しているはず
・時系列を考える。タイムライン表示であれば最初の1~2ページは正しいものを表示させるが、それ以降のページは数秒遅れてもいいかも、など
・サービスとして上限を設ける。Twitterも最大フォロワー数や1日ごとの上限を設けている (有償ユーザは上限緩和)
・ユースケースにより遅延が発生してよいところは ACID を崩す。フォロワー追加時は案1のテーブルにINSERT。Webアプリは基本的に案2のテーブルを見る。毎分、案1のテーブルを読み、案2のテーブルを更新するバッチを動かすなど。例えばAがBをフォローした際、Bがそれをリアルタイムで検知できないくても多分問題はない。一方AはBをフォローした直後からBのコメントがAのタイムラインに出てほしいかもしれない、などと場面場面で遅延が許容されるかを検討する
・インメモリDB。全部メモリ上に乗っけて高速化

あとついでに言うと、100万レコードなら大丈夫と思っていてもいざ全部作って性能試験したら全然ダメで全面的に作り直しとか、サービスがバズって1000万レコード超えちゃったとか、レコード数は100万以下だけど同時利用ユーザが想定の100倍になりDBが持たないというケースも当然ありうるので、最初の段階でいろいろ心配しておくことは大変よいことだと思います。

投稿2023/01/09 11:59

68user

総合スコア2005

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

1人1000レコードx1000人=100万レコードも生成されてしまうのがネックに感じています。

わたしはOracle Databaseで1テーブルで最大42億件のデータを扱ったDWHを使ったことがあります。100万件のデータなんて微々たるものです。一度きちんと正規化されたDBである程度使ってみては?

投稿2023/01/09 06:38

Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meex

2023/01/09 09:02

1テーブルで最大42億件のデータはすごいですね、数百万件でも多いと思ってしまった私にとっては想像もつかない量でした。ちゃんと正規化されていれば万単位のレコードなんて大したことないんですね、ご経験をお教えくださりありがとうございました。
guest

0

1人当たりのレコード数をなるべく減らすことに重点を置いた場合、【案②】以外のやり方でいい方法はありませんでしょうか?

そちらに突き進みたいのであれば、RDBMS以外の、NoSQLを選んだほうがいいでしょう。

「1つのカラムの中にコンマ区切りで追記していく」ようなことをするのは、RDBMSのリレーショナル性を無にするに等しい行為です。

投稿2023/01/08 14:10

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meex

2023/01/09 09:03

そもそもRDBMSは大量レコードを扱うことを想定されていることは新しい気付きになりました。お教えくださりありがとうございした。
guest

0

Neo4j などの Graph DB を使ってみてはいかがでしょう。

投稿2023/01/08 14:21

arcxor

総合スコア2859

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meex

2023/01/09 09:04

Neo4j やGraph DB という手段もあるのですね、データベースの世界はoracle、postgre、MySQLしかないと思っていたので新しい発見でした。とても奥深いのですね、精進します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問