##初めに
久しぶりにデータベース回りをコーディングしていたら、高速化で手こずったので覚書。
所謂、DBのチューニングで検索を高速化するための幾つかの方法になります。
そんなに大したことは書いておりません。
初歩的と言うか基本的なことですね。
参考になれば。
※あくまで高速化に特化した方法を書いておりますが、場合によってはデータの整合性が取れなくなるなどのリスクも発生しますので、ご了承ください。
##DB高速化の方法いくつか
###インデックスを貼る
一応、基本なので詳細は省略します。ですが、貼り方にもコツが必要ですよね。沢山貼れば良いということでもないですし、かといって、検索項目が沢山ある場合は、あるだけ貼りたいし。。。トライアンドエラーで試すしかないですかね。
###集計値は予め集計しておく
メインテーブルと合わせて、サブテーブルの集計値などを表示する場合は、その集計値を予め計算しておいて、メインテーブルのカラムに保存しておくと良いですね。クエリを呼び出すたびにいちいちGROUP BYをしていると遅くなりますからね。
例えば、下記のツイッターで例えると、イイネテーブル(サブテーブル)の集計値をリアルタイムで集計して、ツイートテーブル(メインテーブル)のtweet_num_likeカラム(イイネの数)に反映しておくということかな。
予め出来る処理は、出来るうちにやっておくということですね。
ツイートテーブル(メインテーブル)
カラム | 説明 |
---|---|
tweet_id | ツイートid |
contents | コンテンツ |
num_like | イイネの数 |
イイネテーブル(サブテーブル)
カラム | 説明 |
---|---|
tweet_id | ツイートid |
user_id | イイネしたユーザのuser_id |
###サブデータを連結文字列として保存しておく
場合によっては、サブテーブルのデータ一覧をメインテーブルに連結文字列として保存しておくのもありかなと思います。jsonなどでも良いかもしれませんね。サブテーブルを連結する必要がなくなるので、処理は速くなると思いますが、データ数が増えると容量のコストが増える?
メインテーブル
カラム | 値 |
---|---|
data_id | id_1 |
contents | 'aaaa' |
subdata_param_string | 'param_1@param_2@…' |
###検索条件(WHERE)で、他のテーブルを参照しない
例えば、下記の様なケースで他のテーブルを参照する場合があると思います。
WHERE
column_a IN (SELECT column_a_temp FROM table_1 WHERE ****)
これでも全く問題はないですが、INの中身を予め取得しておいて、値を指定してやるとより速くなります。
###1つのテーブルにデータをまとめておく
色々なケースがあると思いますが、ある程度、リアルタイムでデータが欲しい場合は、テーブルの連結を行うと検索が遅くなるなと思いました。例えば、検索時間を1秒以内に抑えたい場合などにJOINを使うと、データが増えた場合に対応できなくなるなど。
勿論、データ容量が増えたり、他のテーブルとデータが重複したりして管理が大変になるなどのデメリットもあると思いますが、結局、背に腹は代えられず、高速化のためにデータを1つのテーブルに集めておくというのも、場合によってはありかなと思います。
##まとめ
まとめと致しましては、(当たり前の結論にはなりますが、)下記の様にSELECT, FROM, WHERE, ORDER BYのみで完結するようなシンプルなクエリを使用できるまで、データを作成しておくことが重要なのかなと思いました。やっぱりsimple is best.ですかね。
勿論、高速化が正しいということではなく、上述しておりますが、データ重複などのデメリットも存在しますので、ケースによって使い分けるのが大事なのかなと思いました。他にも高速化の方法がありましたら、コメント頂けると幸いですm(_ _)m
SELECT
column_1,
column_2
FROM
table
WHERE
column_a = ****
AND column_b = ****
ORDER BY
column_1,
column_2;