整列時の比較で 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 は遅くなってしまいましたが,ほかは速くなっています.
反映しました.