rails on oracle でいくつかのテーマで検証してみます
●fetchループ
module FetchTest SQL = "select p1.* from posts p1 cross join posts p2" def self.run Post.delete_all 200.times do |i| Post.create(:title => "title_#{i}", :body => "body_#{i}") end open("test.txt", "w") do |f| # ① Post.find_by_sql(SQL).each { |r| f.write "#{r}\r\n" } # ② Post.connection.raw_connection.exec(SQL) { |r| f.write "#{r}\r\n" } end end end FetchTest.run
上記の場合①は通常の検索処理。sqlの実行結果を全てメモリ上に展開します。
②の場合、fetchループで繰り返し処理が発生する為、"同時に必要となるメモリ"は少なくてすみます。
# それぞれ実行しながら、topコマンド等でメモリ利用状況を確認しましょう。
よって大量のcsv出力する場合は必ず②のようにする必要があります。
●DROP
railsで実装する場合、割と頻繁にDBスキーマの全削除、再作成をするかと思います(うちだけ?)。その際の機能は充実してきており、adapter内で多数のDROP文が実装されています。
但し適宜 purge recyclebin してあげないとゴミがたまりそうです。
●indexの表領域
性能向上の為、データ/インデックスを別HDDに保存する場合、データ/インデックスで表領域を分ける必要があります。oracle_enhanced_adapterは成長しており、migrationで
add_index :posts, :title, :tablespace => 'foo'
のように指定できます。
●varchar2問題
oracleのvarchar2/char2は歴史的な経緯で、"バイト単位"での長さ指定になります。
よってrailsからスキーマ作成する際は、string => nvarchar2へのマッピングを以前はしていたのですが、最近のoracle enhanced adapterは進化しています!
lib/active_record/connection_adapters/oracle_enhanced_adapter.rb によれば、nls_length_semantics というオプションがデフォルトで'CHAR'となっており、このオプションを指定する事によってvarchar2/char2を文字数単位で長さ指定出来る様になります。
よって何も考えなくても、mysql等と同じように指定できる様になりました。
実際下記の用にスキーマが出来ています。
SQL> desc posts; 名前 NULL? 型 -------------------------- -------- ---------------------------- ID NOT NULL NUMBER(38) TITLE VARCHAR2(255 CHAR) <= CHARで255 BODY CLOB CREATED_AT DATE UPDATED_AT DATE●oracle enhanced adapter独自項目の設定 oracle enhanced adapterには独自の設定項目があり...と思ったら良いページがありました。一部ソースを読んだ結果下記の様です。
# config/initializers/oracle.rb 等に下記内容を設置 ActiveSupport.on_load(:active_record) do ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do # NUMBER(1)をbooleanにマッピングするか self.emulate_booleans = true # DATE型を(rubyの)Date型にマッピングするか self.emulate_dates = false # カラム名が(^|_)date(_|$)とマッチする場合Date型にマッピングするか self.emulate_dates_by_column_name = false # カラム名が(^|_)idとマッチする場合Integer型にマッピングするか self.emulate_integers_by_column_name = true # CHAR(1)かVARCHAR(1)、またはカラム名が_FLAG/_YNで終了する場合Booleanにマッピングするか self.emulate_booleans_from_strings = true # シーケンサー作成する際のオプションを指定する self.default_sequence_start_value = "1 NOCACHE INCREMENT BY 1" end end●雑感
ソース見て思ったのですが、oracle enhanced adapter マジで進化してます!
かなりきっちりしてる感じです(識別子30文字制限問題、in句の1000上限問題 ...etc)
0 件のコメント:
コメントを投稿