データベースから一度に 1 つのレコードを取得し、必要に応じて処理し、JSON に変換してから、末尾/区切りのカンマを付けて出力できないのはなぜですか?
のみを含むファイルで開始し、[
すべての JSON 文字列を追加した場合、最後のエントリにカンマを追加せず、代わりに終了を使用すると]
、ハッシュの JSON 配列が得られ、一度に 1 行分を処理します。
少し遅くなりますが (おそらく)、システムには影響しません。また、ブロッキング/ページングを使用して一度に適切な数のレコードを取得すると、DB I/O は非常に高速になります。
たとえば、次の Sequel サンプル コードと、行を JSON として抽出し、より大きな JSON 構造を構築するコードを組み合わせたものを次に示します。
require 'json'
require 'sequel'
DB = Sequel.sqlite # memory database
DB.create_table :items do
primary_key :id
String :name
Float :price
end
items = DB[:items] # Create a dataset
# Populate the table
items.insert(:name => 'abc', :price => rand * 100)
items.insert(:name => 'def', :price => rand * 100)
items.insert(:name => 'ghi', :price => rand * 100)
add_comma = false
puts '['
items.order(:price).each do |item|
puts ',' if add_comma
add_comma ||= true
print JSON[item]
end
puts "\n]"
どの出力:
[
{"id":2,"name":"def","price":3.714714089426208},
{"id":3,"name":"ghi","price":27.0179624376119},
{"id":1,"name":"abc","price":52.51248221170203}
]
注文が「価格」順になっていることに注意してください。
検証は簡単です:
require 'json'
require 'pp'
pp JSON[<<EOT]
[
{"id":2,"name":"def","price":3.714714089426208},
{"id":3,"name":"ghi","price":27.0179624376119},
{"id":1,"name":"abc","price":52.51248221170203}
]
EOT
結果は次のとおりです。
[{"id"=>2, "name"=>"def", "price"=>3.714714089426208},
{"id"=>3, "name"=>"ghi", "price"=>27.0179624376119},
{"id"=>1, "name"=>"abc", "price"=>52.51248221170203}]
これにより、JSON が検証され、元のデータが回復可能であることが示されます。データベースから取得した各行は、構築する JSON 構造全体の最小の「バイトサイズ」の部分である必要があります。
それに基づいて、データベース内の着信 JSON を読み取り、操作し、JSON ファイルとして出力する方法は次のとおりです。
require 'json'
require 'sequel'
DB = Sequel.sqlite # memory database
DB.create_table :items do
primary_key :id
String :json
end
items = DB[:items] # Create a dataset
# Populate the table
items.insert(:json => JSON[:name => 'abc', :price => rand * 100])
items.insert(:json => JSON[:name => 'def', :price => rand * 100])
items.insert(:json => JSON[:name => 'ghi', :price => rand * 100])
items.insert(:json => JSON[:name => 'jkl', :price => rand * 100])
items.insert(:json => JSON[:name => 'mno', :price => rand * 100])
items.insert(:json => JSON[:name => 'pqr', :price => rand * 100])
items.insert(:json => JSON[:name => 'stu', :price => rand * 100])
items.insert(:json => JSON[:name => 'vwx', :price => rand * 100])
items.insert(:json => JSON[:name => 'yz_', :price => rand * 100])
add_comma = false
puts '['
items.each do |item|
puts ',' if add_comma
add_comma ||= true
print JSON[
JSON[
item[:json]
].merge('foo' => 'bar', 'time' => Time.now.to_f)
]
end
puts "\n]"
生成するもの:
[
{"name":"abc","price":3.268814929005337,"foo":"bar","time":1379688093.124606},
{"name":"def","price":13.871147312377719,"foo":"bar","time":1379688093.124664},
{"name":"ghi","price":52.720984131655676,"foo":"bar","time":1379688093.124702},
{"name":"jkl","price":53.21477190840114,"foo":"bar","time":1379688093.124732},
{"name":"mno","price":40.99364022416619,"foo":"bar","time":1379688093.124758},
{"name":"pqr","price":5.918738444452265,"foo":"bar","time":1379688093.124803},
{"name":"stu","price":45.09391752439902,"foo":"bar","time":1379688093.124831},
{"name":"vwx","price":63.08947792357426,"foo":"bar","time":1379688093.124862},
{"name":"yz_","price":94.04921035056373,"foo":"bar","time":1379688093.124894}
]
タイムスタンプを追加して、各行が個別に処理されていることを確認できるようにし、行の処理速度を把握できるようにしました。確かに、これは小さなメモリ内データベースであり、コンテンツへのネットワーク I/O はありませんが、適切な DB ホスト上のデータベースへのスイッチを介した通常のネットワーク接続も非常に高速です。ORM に DB をチャンクで読み取るように指示すると、DBM はより大きなブロックを返してパケットをより効率的に満たすことができるため、処理を高速化できます。必要なチャンクのサイズは、ネットワーク、ホスト、およびレコードのサイズによって異なるため、実験して決定する必要があります。
エンタープライズ規模のデータベースを扱う場合、特にハードウェア リソースが限られている場合、元の設計は適切ではありません。何年にもわたって、20,000 行のテーブルが非常に小さいように見える BIG データベースを解析する方法を学びました。最近では VM スライスが一般的であり、それらをクランチに使用しているため、往年の PC であることが多く、メモリ フットプリントが小さく、小さなドライブを備えた単一の CPU です。それらを打ち負かすことはできません。そうしないとボトルネックになるため、データを可能な限り最小のアトミックピースに分割する必要があります。
DB 設計についての口論: JSON をデータベースに格納することは、疑わしい方法です。最近の DBM は行の JSON、YAML、および XML 表現を吐き出すことができますが、保存された JSON、YAML、または XML 文字列内を DBM に強制的に検索させることは、処理速度に大きな影響を与えるため、同等のルックアップ データも持っていない限り、絶対に避けてください。別々のフィールドに索引付けされているため、検索が可能な限り高速になります。データが別々のフィールドで利用できる場合、古き良きデータベースクエリを実行し、DBM または選択したスクリプト言語を調整し、メッセージ化されたデータを出力することがはるかに簡単になります。