書籍を読んだので補足しつつ備忘録…
読んだ書籍はこちら
https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AESQL%E3%83%81%E3%83%A5%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-%E7%A6%8F%E7%94%B0-%E6%AD%A6%E5%BF%97/dp/4797336080
パフォーマンスチューニングとは
処理時間が遅いシステムを早くすること。
と一言で言ってしまうのは簡単なのですが、では何をどうすればよいのかという話
DB周りに集中して紹介します。
ボトルネックの調査
開発環境では往々にしてデータ数が少なく、本番に出した瞬間に重すぎてやばい、ということが起こり得ます。
本番のDBをダンプしたり、psqlなら本番で\timing
を使うなどして心配なクエリを修正した方が得策です
よくある原因
よく原因になりそうなところと解決策を書いていきます
実験に使うテーブルは
レコード数: およそ1000万件
インデックス:update_dateにのみ貼られている
とします。
インデックスが貼られていない
よく取得するカラムにインデックスが貼られていないと、びっくりするくらいレスポンスが遅くなることがあります。
インデックスに関しては、
https://qiita.com/Ohtak/items/8089b8d1fe58ae52cc9d
でも書いたのでよければそちらもどうぞ
ただインデックスを貼る目安は、
全体のデータ量の10%~15%未満のデータを取ってくるとき
だそうなので、全部をselectするようなときには当てはまらない時もあります。
ちなみにpsqlで、
select
id
from
test_table
where
update_date >= current_timestamp + CAST(-96 || 'hour' AS interval);
というクエリを投げた場合の実行時間は、(抽出数の平均は0.1%未満でした)
update_dateにインデックスあり:24848.563ms
update_dateにインデックスなし:108.471 ms
という結果だったので、これだけでかなり早くなります。
インデックスを貼っていないカラムでソートしている
DBにおいて、ソートは時間のかかる処理ですが、それに対してjavaでソートする方が早く済むことがあります。
select
id
from
test_table
order by
create_date;
というクエリの実行時間は15016.297 msですが、
long start = System.currentTimeMillis();
List<Integer> idList = testDao.select();
Collections.sort(idList);
long stop = System.currentTimeMillis();
System.out.println("実行にかかった時間は " + (stop - start) + " ミリ秒です。");
の実行結果は13036msと、わずかにjavaで実行した方が早い結果となりました。
また、インデックスを貼ったカラムはつねにソートされた状態で格納されているため、
select
id
from
test_table
order by
update_date;
では9075.452msという結果になります。
データ量やインデックスを貼っている/貼っていない、その後の処理で何をやるかによって
全体を吟味しながら使い分けた方がよさそうです。
不要なカラムを取ってきている
select
id
from
test_table;
select
*
from
test_table;
の二つを比べた際、
idだけselect :5346.993 ms
全てのカラムをselect:12002.372 ms
という結果になりました。
必要な時でなければ、「とりあえず全部のカラムをとってきとけ」というのは避けた方がよいかも?
(ただ、カラムを一つ取り出すのも二つ取り出すのもSQLの処理的には同じ(はず)なので、単にデータ量がメモリを圧迫してただけとかの可能性もあります。)
頻繁に呼び出すデータのキャッシュが作られていない
たとえインデックスが貼られていても頻繁に呼び出されすぎる、あるいは他が重くなった時問題になることがあります。
マスタデータなど、それほど更新されないデータはキャッシュにしてしまいましょう
まとめ
いろいろ書きましたが、まとめると
・テストするときは本番環境に近づけよう
・インデックスを正しく貼ろう
・必要なデータだけとってこよう
となります。
当然のことを言っているようですが、システムを拡張する際など、意識していないとやらかすときがあるため気をつけましょう。