Redmineで高速に全文検索する方法で紹介したプラグインの新しいバージョンをリリースしてさらに高速化しました。
v0.6.0での変更点
-
検索結果のハイライトにPGroonga/Mroongaの機能を使用するようにしました
- 複数キーワードごとに色分けしないようになりました
-
クエリー構文が使えるようになりました
-
類似チケットの表示をするようにしました
類似チケット
Groongaの類似文書検索の機能を使って類似チケットを表示するようになりました。
例えば、あるソフトウェアのサポートをしているときに似た問い合わせが過去にあれば、その似た問い合わせが類似チケットとして表示されることを期待しています。 現在の実装では、チケットのトラッカー、起票者、担当者、カテゴリなどのメタデータを一切考慮していないので精度はそこそこです。 クリアコード社内で運用しているRedmine1に入れてみたところ類似チケットの検索には15msくらいしかかかっていないのでRedmineの性能に影響はないと考えてデフォルトでONにしてあります。
なぜ高速化したか
元のRedmineの全文検索では、最大で以下の9つのテーブルを検索し、検索時に全件取得してキャッシュしていました。
-
チケット
-
ニュース
-
文書
-
更新履歴
-
Wikiページ
-
メッセージ
-
プロジェクト
-
添付ファイル
-
チケットのコメント
redmine_full_text_search v0.4.0 までは既存のコードをなるべく活かしていたので、クエリの実行数は同じで全件取得していたのも同じでした。
つまり、上記全てのテーブルから検索すると1回のクエリで100msだとしても 9 * 100ms = 900ms
と約1秒かかってしまうことになります。
v0.5.0 では、検索対象のレコードを1つのテーブルにまとめてGroongaの機能を直接使用して全文検索のために実行するクエリを1つにしました。
また、limit と offset を使用して一度に取得するレコード数を減らし、Redmineのキャッシュを使用するのをやめました。
ベンチマーク
-
環境
-
Google Compute Engine
-
n1-standard-2 (vCPUx2, メモリー7.5GB)
-
OS Debian GNU/Linux stretch
-
Ruby 2.3.3p222
-
Redmine 3.4.2
-
Passenger 5.0.30-1+b1
-
MariaDB 10.1.26-0+deb9u1
-
Mroonga 7.06-1
-
PostgreSQL 9.6.4-0+deb9u1
-
PGroonga 2.0.1-1
-
redmine_full_text_searchのバージョンはv0.4.0とv0.6.2を使用しました。 内部ネットワークからMechanizeで特定のユーザーでログインして表にあるクエリーで検索しました。 以下にMariaDB(Mroonga)の場合とPostgreSQL(PGroonga)の場合についてそれぞれの測定結果を示します。
データは、以下のメーリングリストのアーカイブを使用しました。 メーリングリストごとにプロジェクトを作成しました。 メールからチケットを作成し、In-Reply-Toで返信だと判断できる場合は、見つかったチケットへのコメントとして登録するようにしました。
これで31142チケットと72392コメントのデータベースを作成しました。redmine_full_text_search v0.6.2向けのテーブルには103537件レコードが存在します。 Wikiやドキュメント等チケット以外のデータはありません。
測定結果の単位は全てミリ秒です。
MariaDB
Redmine | v0.4.0 | v0.6.2 | |||||
---|---|---|---|---|---|---|---|
query | 1st | 2nd | 1st | 2nd | 1st | 2nd | |
cgi リーク | duration | 1804.86 | 56.0048 | 1028.55 | 62.8551 | 140.443 | 138.351 |
view_runtime | 27.8059 | 29.7982 | 30.5287 | 26.2161 | 61.5869 | 55.7791 | |
db_runtime | 1758.66 | 5.93903 | 969.221 | 7.09439 | 64.5651 | 63.6323 | |
groonga | duration | 1687.73 | 82.2862 | 1053.66 | 124.609 | 119.136 | 115.352 |
view_runtime | 18.7162 | 19.5571 | 25.1116 | 21.4028 | 42.1369 | 39.2488 | |
db_runtime | 1611.95 | 5.80468 | 923.49 | 12.0304 | 63.7171 | 62.6385 | |
mroonga score | duration | 1712.8 | 38.6372 | 1043.22 | 50.2505 | 134.332 | 115.884 |
view_runtime | 19.4748 | 18.8583 | 20.4314 | 21.4807 | 42.9837 | 41.9256 | |
db_runtime | 1678.16 | 5.84049 | 998.232 | 5.45167 | 64.2949 | 61.54 | |
pgrooga score | duration | 1675.0 | 25.8263 | 907.864 | 38.1889 | 72.0365 | 72.458 |
view_runtime | 10.8129 | 10.5722 | 12.1855 | 13.2947 | 12.3002 | 12.2505 | |
db_runtime | 1653.34 | 5.25172 | 877.303 | 5.14269 | 52.3137 | 52.2138 | |
ruby | duration | 1876.77 | 1240.81 | 2858.95 | 1576.22 | 182.263 | 182.67 |
view_runtime | 17.2178 | 17.4677 | 20.9058 | 21.6165 | 44.5798 | 46.555 | |
db_runtime | 683.701 | 9.14142 | 1324.75 | 19.6118 | 108.922 | 106.341 | |
segv | duration | 1734.57 | 97.6753 | 1221.78 | 125.179 | 207.27 | 128.385 |
view_runtime | 51.7349 | 22.1543 | 33.8267 | 31.1135 | 104.215 | 49.5876 | |
db_runtime | 1610.52 | 6.07189 | 1056.77 | 6.53569 | 87.9873 | 62.8314 | |
segv make | duration | 1815.31 | 68.4352 | 958.573 | 72.8359 | 119.899 | 148.094 |
view_runtime | 22.0608 | 32.7035 | 35.3729 | 27.96 | 42.5002 | 67.0567 | |
db_runtime | 1769.95 | 5.81216 | 880.271 | 6.27881 | 64.3565 | 62.977 | |
メモリーリーク | duration | 1665.0 | 49.0786 | 962.625 | 54.4098 | 151.751 | 119.179 |
view_runtime | 21.1638 | 25.3095 | 25.1169 | 23.1611 | 73.9769 | 47.4756 | |
db_runtime | 1626.61 | 5.58291 | 909.367 | 5.83328 | 65.4596 | 60.8111 | |
メモリリーク | duration | 1668.5 | 49.7472 | 1005.86 | 56.3724 | 111.954 | 111.491 |
view_runtime | 22.01 | 22.3757 | 18.6613 | 20.756 | 41.0274 | 40.3688 | |
db_runtime | 1620.18 | 5.67121 | 947.36 | 5.73328 | 60.8254 | 59.7722 | |
ライトニングトーク カンファレンス 開催 | duration | 1730.69 | 39.2599 | 950.232 | 48.4056 | 122.699 | 117.899 |
view_runtime | 18.879 | 20.1971 | 24.7018 | 21.0985 | 43.9869 | 42.6021 | |
db_runtime | 1697.25 | 5.37024 | 901.403 | 5.60327 | 65.7128 | 63.2021 | |
発表者 募集 | duration | 1540.63 | 41.1723 | 1026.68 | 46.5856 | 116.767 | 114.665 |
view_runtime | 18.8667 | 18.5547 | 20.2438 | 19.4315 | 42.4205 | 42.7707 | |
db_runtime | 1505.5 | 5.52283 | 982.723 | 5.2658 | 62.3322 | 60.5112 | |
勉強会 会議 | duration | 1535.28 | 39.5411 | 948.463 | 47.6093 | 114.435 | 137.902 |
view_runtime | 17.7493 | 19.1658 | 19.8384 | 19.5605 | 41.9521 | 40.7409 | |
db_runtime | 1501.66 | 5.67893 | 904.492 | 5.73054 | 61.676 | 60.6336 |
平均と標準偏差は以下の通りです。
Redmine | v0.4.0 | v0.6.2 | |||||
---|---|---|---|---|---|---|---|
1st | 2nd | 1st | 2nd | 1st | 2nd | ||
平均 | duration | 1703.93 | 152.37 | 1163.87 | 191.96 | 132.75 | 125.19 |
view_runtime | 22.21 | 21.39 | 23.91 | 22.26 | 49.47 | 43.86 | |
db_runtime | 1559.79 | 5.97 | 972.95 | 7.53 | 68.51 | 64.76 | |
標準偏差 | duration | 97.12 | 328.76 | 516.86 | 418.29 | 33.65 | 25.04 |
view_runtime | 9.66 | 5.57 | 6.41 | 4.36 | 21.41 | 12.19 | |
db_runtime | 275.78 | 0.98 | 117.69 | 4.05 | 14.46 | 12.87 |
MariaDBの場合はほぼ想定通りの測定結果でした。 プラグインなしの場合は、DBアクセスに初回1500ms以上かかっていたのが2回目は5ms前後になっていてキャッシュが効いています。 プラグインv0.4.0の場合は、DBアクセスに初回1000ms前後にかかってており、2回目は5ms前後になっていました。 プラグインv0.6.2の場合は、DBアクセスに初回、2回目ともに50-100ms程度かかっており、初回の検索から速いのでキャッシュしなくても十分な速度が出ています。
プラグインなしの場合とv0.6.2の場合を比較すると、初回の検索で約24倍高速になっています。
db_runtimeの標準偏差を見ると、v0.6.2のとき最も値が小さくなっており、安定して高速に動作することがわかります。
PostgreSQL
Redmine | v0.4.0 | v0.6.2 | |||||
---|---|---|---|---|---|---|---|
query | 1st | 2nd | 1st | 2nd | 1st | 2nd | |
cgi リーク | duration | 5432.23 | 5708.34 | 91.9298 | 91.6952 | 205.405 | 207.645 |
view_runtime | 24.3255 | 26.9705 | 31.3033 | 37.1955 | 39.1355 | 50.9562 | |
db_runtime | 5385.85 | 5660.76 | 29.0279 | 29.6823 | 145.829 | 144.418 | |
groonga | duration | 5060.77 | 5071.71 | 669.003 | 647.418 | 185.603 | 182.977 |
view_runtime | 24.3327 | 20.2376 | 26.1071 | 40.4994 | 30.0942 | 30.011 | |
db_runtime | 4933.86 | 4929.92 | 560.77 | 522.823 | 146.799 | 144.304 | |
mroonga score | duration | 5177.38 | 5167.46 | 69.7063 | 64.5032 | 181.835 | 181.996 |
view_runtime | 20.2529 | 20.5412 | 26.1367 | 23.6614 | 29.0306 | 28.7275 | |
db_runtime | 5139.11 | 5127.81 | 22.2003 | 21.8169 | 144.434 | 143.932 | |
pgrooga score | duration | 5037.87 | 5056.32 | 46.4337 | 43.408 | 153.975 | 159.449 |
view_runtime | 11.5761 | 11.7345 | 15.6785 | 14.6403 | 12.8356 | 12.9991 | |
db_runtime | 5013.34 | 5031.37 | 14.6134 | 14.7022 | 134.023 | 138.259 | |
ruby | duration | 3542.06 | 3402.16 | 19749.8 | 19558.4 | 238.018 | 222.578 |
view_runtime | 18.2419 | 18.4601 | 18.6485 | 26.2439 | 43.0062 | 29.8173 | |
db_runtime | 1511.17 | 1508.25 | 18214.4 | 17921.3 | 184.03 | 182.523 | |
segv | duration | 5270.42 | 5333.98 | 522.433 | 443.14 | 384.031 | 190.565 |
view_runtime | 28.5796 | 26.4264 | 43.9667 | 33.4644 | 90.3281 | 35.4176 | |
db_runtime | 5104.6 | 5174.81 | 351.514 | 309.031 | 283.627 | 144.746 | |
segv make | duration | 5691.51 | 5691.54 | 153.903 | 145.227 | 190.858 | 201.922 |
view_runtime | 27.0135 | 27.8609 | 44.5491 | 40.7997 | 32.3304 | 43.489 | |
db_runtime | 5613.84 | 5617.51 | 66.682 | 64.3612 | 148.758 | 147.865 | |
メモリーリーク | duration | 5789.28 | 5752.14 | 75.0013 | 72.5004 | 195.717 | 200.674 |
view_runtime | 23.1544 | 21.7764 | 20.2103 | 21.5645 | 41.4241 | 45.2702 | |
db_runtime | 5740.95 | 5709.43 | 33.8974 | 31.4955 | 141.669 | 143.453 | |
メモリリーク | duration | 5749.46 | 5792.81 | 105.487 | 102.567 | 196.678 | 187.858 |
view_runtime | 23.1136 | 22.6125 | 21.9238 | 23.339 | 37.9664 | 35.4135 | |
db_runtime | 5696.29 | 5738.85 | 57.3894 | 54.1745 | 143.913 | 142.159 | |
ライトニングトーク カンファレンス 開催 | duration | 5842.91 | 5811.98 | 63.857 | 66.4787 | 187.346 | 185.818 |
view_runtime | 20.0885 | 22.1672 | 22.3308 | 23.4369 | 30.5955 | 29.236 | |
db_runtime | 5804.88 | 5770.79 | 22.9653 | 23.6612 | 146.704 | 146.915 | |
発表者 募集 | duration | 5154.93 | 5152.25 | 74.2416 | 73.2 | 183.645 | 181.342 |
view_runtime | 20.5156 | 19.2945 | 27.7632 | 29.5588 | 31.441 | 30.5509 | |
db_runtime | 5114.81 | 5112.4 | 24.3069 | 23.246 | 143.74 | 141.939 | |
勉強会 会議 | duration | 5028.9 | 5064.46 | 65.7615 | 78.8453 | 180.065 | 182.6 |
view_runtime | 19.6628 | 18.504 | 21.4198 | 33.3649 | 29.5505 | 30.3836 | |
db_runtime | 4989.92 | 5025.62 | 24.977 | 24.7126 | 142.494 | 143.389 |
平均と標準偏差は以下の通りです。
Redmine | v0.4.0 | v0.6.2 | |||||
---|---|---|---|---|---|---|---|
1st | 2nd | 1st | 2nd | 1st | 2nd | ||
平均 | duration | 5231.48 | 5250.43 | 1807.30 | 1782.28 | 206.93 | 190.45 |
view_runtime | 21.74 | 21.38 | 26.67 | 28.98 | 37.31 | 33.52 | |
db_runtime | 5004.05 | 5033.96 | 1618.56 | 1586.75 | 158.84 | 146.99 | |
標準偏差 | duration | 590.01 | 633.07 | 5413.33 | 5362.64 | 56.54 | 15.34 |
view_runtime | 4.26 | 4.25 | 8.84 | 7.84 | 17.67 | 9.38 | |
db_runtime | 1096.48 | 1107.02 | 5006.48 | 4927.30 | 39.38 | 10.96 |
PostgreSQLの場合は、プラグインなしのときは初回、2回目ともにDBアクセスに約5秒かかっているのでキャッシュが効いていないことがわかります。 v0.4.0の場合もキャッシュが効いておらず、初回、2回目ともにDBアクセスに約1.5秒かかっています。プラグインなしと比較して、約3倍高速になりました。 v0.6.2ではRedmineのキャッシュを使用しないようにしたので、キャッシュの影響はありません。初回、2回目ともにDBアクセスに約0.15秒かかっています。 プラグインなしと比較すると、約33倍高速になりました。v0.4.0と比較すると約10倍高速になっています。
db_runtimeの標準偏差を見ると、v0.6.2のとき最も値が小さくなっており、安定して高速に動作することがわかります。
MariaDBとPostgreSQLの比較
redmine_full_text_search v0.6.2の場合、MariaDBとPostgreSQLのdb_runtimeの平均を比較するとMariaDBの方が約2.3倍高速という結果でした。 これは、MroongaとPGroongaでGroonga上のテーブル定義やインデックス定義に違いがあるためではないかと考えています。
まとめ
今後は、機能を充実させつつMariaDBとPostgreSQLのどちらを使っても快適に検索できるようにしていきたいです。 やりたいことについてはプロジェクトのissuesも見てください。
-
チケット数は約4000件 ↩