groonga/grnxx

整列時の比較で N/A を意識しなくてすむように変換する

Closed this issue · 5 comments

概要

整列時の比較で N/A かどうかを確認していると無駄が多くなるため,整列用のデータを投入する時点で N/A を意識せず比較できるように変換します.
たとえば, Int を昇順に整列するのであれば, raw() - 1 を整列条件とすることで,単純な int64_t の整列になります.

実験(Int, N/A なし)

簡単に確認できそうなので, 2^21 行(約 210 万行)からなるテーブルの全レコードを整列するのにかかる時間を調べてみました.

カラムの内容は以下の通りです.

  • Int_1: 0 以上 255 以下の擬似乱数.
  • Int_2: 0 以上 65535 以下の擬似乱数.
  • Int_3: 範囲制限なしの擬似乱数.
Sort conditions Old [s] New [s]
Int_1 0.089 0.083
Int_2 0.170 0.155
Int_3 0.218 0.199
Int_1, Int_2 0.241 0.223
Int_1, Int_3 0.243 0.225
Int_2, Int_3 0.251 0.240
Int_1, Int_2, Int_3 0.263 0.249

Old は比較時に N/A を考慮する実装で, New はデータ投入時に変換する実装です.
N/A を含まなくても,少しは短縮につながるようです.
N/A が含まれていれば,差は拡がるはずです.

上記 New は Expression を評価してから変換をおこなっていますが, Expression に変換まで組み込むことにより,無駄を抑えることができます.

実験(Int, N/A あり)

各カラムの 25% を N/A にして試してみました.

Sort conditions Old [s] New [s]
Int_1 0.089 0.076
Int_2 0.170 0.131
Int_3 0.215 0.162
Int_1, Int_2 0.237 0.196
Int_1, Int_3 0.239 0.200
Int_2, Int_3 0.256 0.229
Int_1, Int_2, Int_3 0.265 0.253

Old の方はあまり変化していませんが, New の方は少し速くなっています.
Old が遅くなっていないのは,基本クイックソートなので N/A は序盤に後ろへと固められてしまうからだと思います.
New が速くなっているのも同様の理由でしょう.

とりあえず,整列については最初に変換という方針で良さそうです.

実験(Float, N/A なし)

Float についても同様に試してみました.

Sort conditions Old [s] New [s]
Float_1 0.102 0.088
Float_2 0.201 0.158
Float_3 0.252 0.203
Float_1, 2 0.274 0.228
Float_1, 3 0.273 0.229
Float_2, 3 0.282 0.249
Float_1, 2, 3 0.296 0.255

Int より差が大きくなっています.

実験(Float, N/A なし)

整列用の値に変換する箇所に無駄を見つけて修正したところ,以下に示す結果となりました.
New2 が修正後の所要時間です.

Sort conditions Old [s] New [s] New2[s]
Float_1 0.102 0.088 0.080
Float_2 0.201 0.158 0.136
Float_3 0.252 0.203 0.166
Float_1, 2 0.274 0.228 0.204
Float_1, 3 0.273 0.229 0.208
Float_2, 3 0.282 0.249 0.233
Float_1, 2, 3 0.296 0.255 0.264

Float_1, 2, 3 は遅くなってしまいましたが,ほかは速くなっています.

反映しました.