そこで、私は小さなデータ処理タスクを処理するPythonプログラムを作成しました。
これが私が望む計算の構成言語での非常に簡単な仕様です:
parse "%s %lf %s" aa bb cc | group_by aa | quickselect --key=bb 0:5 | \
flatten | format "%s %lf %s" aa bb cc
つまり、各行について、単語、浮動小数点数、および別の単語を解析します。それらをプレーヤーID、スコア、および日付と考えてください。各プレイヤーの上位5つのスコアと日付が必要です。データサイズは簡単ではありませんが、巨大ではありません。約630メガバイト。
同様に短く(以下のPythonのように)、はるかに高速にするために、実際に実行可能な言語をどのように記述すべきかを知りたいです。
#!/usr/bin/python
# -*- coding: utf-8; -*-
import sys
top_5 = {}
for line in sys.stdin:
aa, bb, cc = line.split()
# We want the top 5 for each distinct value of aa. There are
# hundreds of thousands of values of aa.
bb = float(bb)
if aa not in top_5: top_5[aa] = []
current = top_5[aa]
current.append((bb, cc))
# Every once in a while, we drop the values that are not in
# the top 5, to keep our memory footprint down, because some
# values of aa have thousands of (bb, cc) pairs.
if len(current) > 10:
current.sort()
current[:-5] = []
for aa in top_5:
current = top_5[aa]
current.sort()
for bb, cc in current[-5:]:
print aa, bb, cc
入力データの例を次に示します。
3 1.5 a
3 1.6 b
3 0.8 c
3 0.9 d
4 1.2 q
3 1.5 e
3 1.8 f
3 1.9 g
これが私がそれから得た出力です:
3 1.5 a
3 1.5 e
3 1.6 b
3 1.8 f
3 1.9 g
4 1.2 q
、には7つの値があり、値が上位5から外れるため、との値3
を削除します。値が1つしかないため、その「上位5」はその1つの値のみで構成されます。c
d
bb
4
これは、MySQLで同じクエリを実行するよりも高速に実行されます(少なくとも、クエリを実行する方法で)が、ほとんどの時間をPythonバイトコードインタープリターに費やしていると確信しています。別の言語では、おそらく1分あたりではなく1秒あたり数十万行を処理できると思います。ですから、より高速な実装の言語で書きたいと思います。
しかし、どの言語を選ぶべきかわかりません。
これをSQLで単一のクエリとして表現する方法を理解できていません。実際
select * from foo into outfile 'bar';
、入力データだけでもMySQLの機能に感心していません。
Cは当然の選択ですが、line.split()
2タプルのリストの並べ替え、ハッシュテーブルの作成などでは、標準ライブラリにないコードを記述する必要があるため、14行ではなく100行以上のコードになります。
C ++の方が良い選択のようですが(標準ライブラリに文字列、マップ、ペア、およびベクトルがあります)、コードはSTLでかなり乱雑になるようです。
OCamlは問題ありませんが、同等のものがありline.split()
ますか?そのマップのパフォーマンスについては悲しいですか?
Common Lispは機能するかもしれませんか?
ループを高速コードにプッシュダウンできる、このようなデータベース計算用のMatlabに相当するものはありますか?誰かが豚を試しましたか?
(編集:サンプルの入力および出力データを提供することでdavethegr8のコメントに応答し、Pythonプログラムのバグを修正しました!)
(追加編集:うわー、このコメントスレッドはこれまでのところ本当に素晴らしいです。ありがとう、みんな!)
編集:
2007年にsbcl-develで不気味に似た質問がありました(ありがとう、Rainer!)。awk
これは、いくつかのテストデータを生成するためのWill Hartungのスクリプトです(実際のデータのジップの分布はありませんが)。
BEGIN {
for (i = 0; i < 27000000; i++) {
v = rand();
k = int(rand() * 100);
print k " " v " " i;
}
exit;
}