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

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

新規登録して質問してみよう
ただいま回答率
85.47%
MySQL

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

Q&A

解決済

2回答

272閲覧

MySQLの1テーブルに多くの件数を保持したい場合に出来る対策は何がありますか。

ra-n

総合スコア17

MySQL

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

0グッド

0クリップ

投稿2023/12/26 14:08

編集2023/12/26 14:13

実現したいこと

MySQLを使ったシステムのテーブル定義を考えています。
1テーブルに多くの件数を保持したい場合、どのような対策をしたら良いのか知りたいです。

前提

ユーザが質問に対してどのような回答したかを保持したいです。
テーブルのカラムとしては以下を想定しています。

IDユーザID質問ID回答ID
1234

【件数の想定】
ユーザの件数は2000件、質問の件数は300件を想定しています。
IDがプライマリキー、ユーザIDと質問IDがユニークキーになります。

【使用イメージ】
システムが動いている間、絶えず検索、追加、変更が行われるテーブルです。
検索時はユーザIDのみで検索、ユーザIDと質問IDで検索する2パターンがあります。

疑問

件数を想定する際、念のため数倍を想定した方が良いのかと思いました。
仮に3倍を想定すると

ユーザ6,000件×質問900件=レコード数は5,400,000件

となり、相当アクセスに時間がかかるテーブルになってしまうのではないかと懸念しています。

考えたこと

件数が多くなるのでユーザIDと質問IDを組み合わせたインデックスを定義しようと考えました。
ただ、頻繁に追加が発生するテーブルなので追加の処理が遅くなる方が不都合なので
インデックスは解決案としてふさわしくない気がしました。

次にパーティションを考えました。
調べたところ、キーじゃないと指定できないとあったので、ユーザIDと質問IDを指定すれば良いのかと考えています。

ただ、本テーブルの検索時はユーザIDのみで検索する場合が多いので
IDとユーザIDをプライマリキーにし直すことになるのか?というあたりが分かっていません。

教えていただきたいこと

  1. テーブルのインデックスは今回の場合ふさわしくないという考え方は合っていますか。
  2. パーティションを使えば良いという考え方は合っていますか。合っている場合、どのカラムをパーティションのキーにすれば良いか、どのように考えれば良いのか教えてください。
  3. 他に出来る対策があれば教えてください。

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

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

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

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

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

guest

回答2

0

いろいろフワフワしてて、まだプロトタイプを作る段階でもない感じなのかと思いますが、多分モノがないとイメージできないのだと思うので、何か作る前提で考えてみた結果を書いておきます。回答となるのかどうかは分かりません。

テーブルについて

回答についてのテーブルなら回答テーブルでいいと思います。

想定件数について

現実的な予想が必要です。想定ができないなら無理にする必要はなく、一旦これくらいと置いた仮定の数字が1つあればいいと思います。例えばteratailなら、およそ

  • ユーザー15万くらい(ランキングから分かる)
  • 質問40万くらい(この質問のデータから目算)
  • 回答30万くらい(同上目分量で)

ではないかと思います。テストデータの都合からこれを

  • ユーザー26万くらい
  • 質問52万くらい
  • 回答52万くらい

にして一度試してみればいいでしょう。

本来は要件から出る数字なので、勝手に決めちゃいけませんし、これによりハードウェアスペック、引いては予算などを決めます。逆に言えば使えるハードウェアスペックが限られているならそちらの要件に寄せる必要があり、そのスペックの中で、およそここまでなら行けそうだという数字を提示する必要があります。

登録・検索速度について

目標とする性能があるなら、数字として出さないといけません。例えば

  • 日に何件登録可能である
  • 1時間に何件程度検索できる必要がある
  • 登録に1件何秒まで待てる
  • 検索に1件何秒まで待てる

などの数字です。ないならないで、テストデータを作り、この件数でこの内容のデータならそれぞれどれくらい捌けるという数字を提示する必要があります。

テストデータについて

現状何も決まっておらず、何の想定もなく、スペックが足りるのかどうかも分からないので、それらが決められるように作りましょう。普通に考えると、インデックスは必要に決まってるので、つけましょう。

とりあえず作ったサンプルだけ置いておきます。

bash

1PASS="hogepass" 2cat >hoge.sql <<EOF 3set profiling=1; 4CREATE TABLE User ( 5 id varchar(20) PRIMARY KEY, 6 name varchar(100) NOT NULL 7); 8CREATE TABLE Question ( 9 id integer AUTO_INCREMENT PRIMARY KEY, 10 user varchar(20) NOT NULL, 11 content TEXT NOT NULL 12); 13CREATE TABLE Answer ( 14 id integer AUTO_INCREMENT PRIMARY KEY, 15 question integer NOT NULL, 16 user varchar(20) NOT NULL, 17 content TEXT NOT NULL 18); 19EOF 20echo "INSERT INTO User VALUES ('1', 'UserName1');" >>hoge.sql 21num=1 22for i in $(seq 18); do 23 echo "INSERT INTO User SELECT cast((cast(id as signed)+${num}) as char), concat('UserName', cast((cast(id as signed)+${num}) as char)) FROM User;" 24 num=$(echo $num + $num | bc) 25done >>hoge.sql 26echo "INSERT INTO Question VALUES(NULL, '1', 'QuestionContent1');" >>hoge.sql 27num=1 28for i in $(seq 19); do 29 echo "INSERT INTO Question select NULL, cast(mod(id+${num}-1, 262144)+1 as char), concat('QuestionContent', cast(id+${num} as char)) from Question;" 30 num=$(echo $num + $num | bc) 31done >>hoge.sql 32echo "INSERT INTO Answer VALUES(NULL, 1, 1, 'AnswerContent1');" >>hoge.sql 33num=1 34for i in $(seq 19); do 35 echo "INSERT INTO Answer select NULL, mod(id+${num}-1, 524288)+1, cast(mod(id+${num}-1, 262144) as char)+1, concat('AnswerContent', cast(id+${num} as char)) from Answer;" 36 num=$(echo $num + $num | bc) 37done >>hoge.sql 38cat >>hoge.sql <<EOF 39analyze table User, Question, Answer; 40create index Question_user on Question(user); 41create index Answer_question on Answer(question); 42create index Answer_user on Answer(user); 43select count(*) from User; 44select count(*) from Question; 45select count(*) from Answer; 46select U.name as 質問者, Q.content as 質問, A.content as 回答, AU.name as 回答者 from User as U inner join Question as Q on U.id=Q.user inner join Answer as A on Q.id=A.question inner join User as AU on A.user=AU.id where U.id in ('1','3','5'); 47show profiles; 48exit; 49EOF 50docker run -d --rm --name hoge_mysql -v $(pwd)/data:/var/lib/mysql -v $(pwd):/home/mysql -e MYSQL_ROOT_PASSWORD=${PASS} mysql:8 51docker exec -i -w /home/mysql hoge_mysql bash <<EOF 52while ! mysql -u root --password=${PASS} </dev/null;do 53 sleep 1 54done 55mysql -u root --password=${PASS} --verbose --table <<EOF2 56create database hoge; 57exit; 58EOF2 59LC_CTYPE=C.UTF-8 mysql -u root --password=${PASS} --database=hoge --verbose --table <hoge.sql 60exit 61EOF 62docker stop hoge_mysql

本来はチューニングなども必要です。

投稿2023/12/27 02:50

編集2023/12/27 03:08
dameo

総合スコア943

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

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

ra-n

2023/12/28 14:14

ご回答いただきありがとうございました。 登録・検索速度について、どのようなところを気にしていかなければならないのか 参考にさせていただきます。
guest

0

ベストアンサー

まず定義テーブルについてはユーザID/質問IDのユニーク属性が必須です。
ユニークはインデックスを兼ねるのでそれ以上のインデックスの付加はおそらく不要ですが
検索・集計仕様にあわせて必要でしたら追加してください

またカラム数も少なく500万件程度なら特殊な処理は不要だと思います。
これも検索・集計をどうしたいかによるのでなんともいえません。
テストデータをつくって反応をみてチューニングするくらいでちょうどよいかもしれません

投稿2023/12/27 01:24

yambejp

総合スコア114883

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

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

ra-n

2023/12/28 14:16

ご回答いただきありがとうございます。 500万件なら特殊な処理は不要という具体的な数字をご提示いただけたので、 いったん、このまま何もせずに進んでみようと判断が出来ました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問