ActiveRecord::Base storeã®é度æ¤è¨¼
Rails 3.2.0ãã追å ãããæ©è½
3.2.0ãªãªã¼ã¹ãã1å¹´è¿ããã£ã¦ãã¦ã
ä»æ´ãªæãã§ãããæè¿ä½¿ã£ã¦ããã©ã¼ãã³ã¹çã«çãæããããã®ã§ã
ã¡ããã¨è¨æ¸¬ãã¦ã¿ã¾ããã
æ©è½ï¼ç¨éã®èª¬æã¯ããã¡ãã«ãã¾ããã
http://d.hatena.ne.jp/hichiriki/20120229
ãã£ããè¨æ¸¬ã(rails 3.2.11)
ç¨æãããã¼ãã«
$ rails g model store3 # storeã§3ã«ã©ã (å®éã«ã¯ textã«ã©ã 1ã¤)
$ rails g model store10 # storeã§10ã«ã©ã (å®éã«ã¯ textã«ã©ã 1ã¤)
$ rails g model store30 # storeã§30ã«ã©ã (å®éã«ã¯ textã«ã©ã 1ã¤)$ rails g model serialize3 # serializeã§3ã«ã©ã (å®éã«ã¯ textã«ã©ã 1ã¤)
$ rails g model serialize10 # serializeã§10ã«ã©ã (å®éã«ã¯ textã«ã©ã 1ã¤)
$ rails g model serialize30 # serializeã§30ã«ã©ã (å®éã«ã¯ textã«ã©ã 1ã¤)$ rails g model normal3 # å®éã«3ã«ã©ã
$ rails g model normal10 # å®éã«10ã«ã©ã
$ rails g model normal30 # å®éã«30ã«ã©ã
åã«ã©ã æ°ã§ã®ãã«ã©ã å
3ã«ã©ã : num1, str1, time1
10ã«ã©ã : num1, num2, num3, num4, str1, str2, str3, str4, time1, time2
30ã«ã©ã : num1-15, str1-10, time1-5
insert
require 'benchmark' now = Time.now three_columns = {num1: 1, str1: 'a', time1: now} ten_columns = {num1: 1, num2: 2, num3: 3, num4: 4, str1: 'a', str2: 'b', str3: 'c', str4: 'd', time1: now, time2: now} thirty_columns = {num1: 1, num2: 2, num3: 3, num4: 4, num5: 5, num6: 6, num7: 7, num8: 8, num9: 9, num10: 10, num11: 11, num12: 12, num13: 13, num14: 14, num15: 15, str1: 'a', str2: 'b', str3: 'c', str4: 'd', str5: 'e', str6: 'f', str7: 'g', str8: 'h', str9: 'i', str10: 'j', time1: now, time2: now, time3: now, time4: now, time5: now} n = 1000 Benchmark.bm do |x| x.report('store3') { n.times{Store3.create!(three_columns)} } x.report('store10') { n.times{Store10.create!(ten_columns)} } x.report('store30') { n.times{Store30.create!(thirty_columns)} } x.report('serialize3') { n.times{Serialize3.create!(text: three_columns)} } x.report('serialize10') { n.times{Serialize10.create!(text: ten_columns)} } x.report('serialize30') { n.times{Serialize30.create!(text: thirty_columns)} } x.report('normal3') { n.times{Normal3.create!(three_columns)} } x.report('normal10') { n.times{Normal10.create!(ten_columns)} } x.report('normal30') { n.times{Normal30.create!(thirty_columns)} } end
$ rails runner script/benchmark.rb
user system total real
store3 2.150000 0.160000 2.310000 ( 3.218724)
store10 2.600000 0.130000 2.730000 ( 3.445697)
store30 4.980000 0.170000 5.150000 ( 6.126592)
serialize3 1.770000 0.120000 1.890000 ( 2.484414)
serialize10 2.390000 0.130000 2.520000 ( 3.181018)
serialize30 4.060000 0.150000 4.210000 ( 5.224046)
normal3 1.330000 0.120000 1.450000 ( 1.945207)
normal10 1.800000 0.120000 1.920000 ( 2.531964)
normal30 3.240000 0.150000 3.390000 ( 4.348845)
ãã£ã1000åã§ããããªãã«å·®ãåºãã
select
require 'benchmark' now = Time.now three_columns = {num1: 1, str1: 'a', time1: now} ten_columns = {num1: 1, num2: 2, num3: 3, num4: 4, str1: 'a', str2: 'b', str3: 'c', str4: 'd', time1: now, time2: now} thirty_columns = {num1: 1, num2: 2, num3: 3, num4: 4, num5: 5, num6: 6, num7: 7, num8: 8, num9: 9, num10: 10, num11: 11, num12: 12, num13: 13, num14: 14, num15: 15, str1: 'a', str2: 'b', str3: 'c', str4: 'd', str5: 'e', str6: 'f', str7: 'g', str8: 'h', str9: 'i', str10: 'j', time1: now, time2: now, time3: now, time4: now, time5: now} n = 1000 Benchmark.bm do |x| x.report('store3') { Store3.limit(n).all.map(&:num1) } x.report('store10') { Store10.limit(n).all.map(&:num1) } x.report('store30') { Store30.limit(n).all.map(&:num1) } x.report('serialize3') { Serialize3.limit(n).all.map{|s|s.text[:num1]} } x.report('serialize10') { Serialize10.limit(n).all.map{|s|s.text[:num1]} } x.report('serialize30') { Serialize30.limit(n).all.map{|s|s.text[:num1]} } x.report('normal3') { Normal3.limit(n).all.map(&:num1) } x.report('normal10') { Normal10.limit(n).all.map(&:num1) } x.report('normal30') { Normal30.limit(n).all.map(&:num1) } end
.allã§ãããã¨ããã¼ãããã¦ãªãããã ã£ãã®ã§ãã«ã©ã ã«è§¦ãã¨ããæå³ã§mapãã¦ã¾ãã
$ rails runner script/benchmark.rb
user system total real
store3 0.650000 0.040000 0.690000 ( 0.725642)
store10 0.630000 0.010000 0.640000 ( 0.652668)
store30 1.670000 0.010000 1.680000 ( 1.684106)
serialize3 0.330000 0.020000 0.350000 ( 0.385289)
serialize10 0.650000 0.010000 0.660000 ( 0.668932)
serialize30 1.690000 0.010000 1.700000 ( 1.716288)
normal3 0.090000 0.000000 0.090000 ( 0.093420)
normal10 0.130000 0.000000 0.130000 ( 0.132085)
normal30 0.200000 0.010000 0.210000 ( 0.216454)
ãªãã¸ã§ã¯ãã«ããã¨ãããã¨ã¦ãéãã
容é
show table statusã®Data_length (1000件)
store3s: 131,072
store10s: 245,760
store30s: 1,589,248serialize3s: 131,072
serialize10s: 245,760
serialize30s: 1,589,248normal3s: 65,536
normal10s: 98,304
normal30s: 196,608
storeã¨serializeãã¾ã£ããåããã©ã£ã¡ãyamlããªï¼
å½ç¶ãªããstoreã¨serializeã¯ãã¨ã¦ã大ããã
çµè«
åºæ¬çã«é ãã容éã大ãããªãã®ã§ã使ãå ´æã¯ããèããæ¹ããããã
ããã·ã¥ã®å¤ã宣è¨ã¨åæã«åç §ããæ¹æ³
ä¹ ã ã«æ´æ°ãã¾ãããããªãèªåç¨ã®ã¡ã¢ã§ãorz
ruby ã ã¨ä»¥ä¸ã®ããã«æ¸ãã®ãperlã§ã©ãæ¸ãã°ããã®ããã
# ruby # ç¡åããã·ã¥(ã¨ããå¼ã³æ¹ã§ãããããããªããã©)ãä½æã¨åæã«å¤ãå¼ã£å¼µã {:k1 => 'v1', :k2 => 'v2'}[:k2] # ==> "v2"
ä¸å¿ããããªæãã§æ¸ãããã©ããªãã¡ã¬ã³ã¹ã«ããã«å¼ã£å¼µãæ¹æ³ã¯ãããããã
# perl {k1 => 'v1', k2 => 'v2'}->{k2} # ==> "v2" (k1 => 'v1', k2 => 'v2'){k2} # syntax error...
é
åã ã¨rubyã¨åãæãã§ã§ãããã ãã©ãªãã
# ruby # ç¡åé åãä½æã¨åæã«å¤ãå¼ã£å¼µã %w[one two three][1] # ==> "two"
# perl qw(one two three)[1] # ==> "two"
image_tagã§ä»å ãããç»åã®ã¿ã¤ã ã¹ã¿ã³ãããproductionç°å¢ã§ãç»åãã¡ã¤ã«ãæ´æ°ãããã¿ã¤ãã³ã°ã§æ´æ°ãããããã«ãã
image_tagã§ç»åã表示ããéã«ãsrcã®å¾ãã«ä»ãã¿ã¤ã ã¹ã¿ã³ãã¯
åºæ¬çã«ã¯ File.mtime(image_path) ãªã®ã§ãç»åãã¡ã¤ã«ã®æçµæ´æ°æå»ã§ãã
image_tag 'rails.png' #=> <img src="/images/rails.png?1298610241" alt="Rails" />
ãªã®ã§ãdevelopementç°å¢ã§ã¯ç»åãã¡ã¤ã«ãtouchãã¦ããããããã¨ãã¿ã¤ã ã¹ã¿ã³ããæ´æ°ããã¾ãã
ããããproductionç°å¢ã§ã¯touchãã¦ãæ´æ°ããã¾ããã(passengerãªãããµã¼ãããªã¹ã¿ã¼ãããã°æ´æ°ããã¾ã)
ãªããããªããã¯ãActionView::Helpers::AssetTagHelper ã® rails_asset_id ã¡ã½ãããè¦ãã¨ãããã¾ãã
# File actionpack/lib/action_view/helpers/asset_tag_helper.rb def rails_asset_id(source) if asset_id = ENV["RAILS_ASSET_ID"] asset_id else if @@cache_asset_timestamps && (asset_id = @@asset_timestamps_cache[source]) asset_id else path = File.join(ASSETS_DIR, source) asset_id = File.exist?(path) ? File.mtime(path).to_i.to_s : '' if @@cache_asset_timestamps @@asset_timestamps_cache_guard.synchronize do @@asset_timestamps_cache[source] = asset_id end end asset_id end end end
æåï¼åã¯ãFile.mtime(path) ãã¡ããã¨åã£ã¦ãããã®ã§ããã
ãã®éã«ã@@asset_timestamps_cache[source] = asset_id ã§ããã£ãã·ã¥ãã¦ã
以éã¯ããã®ãã£ãã·ã¥ã使ããã¾ãã
ã§ã@@cache_asset_timestamps ãä½ããè¦ãã¨
# File actionpack/lib/action_view/helpers/asset_tag_helper.rb def self.cache_asset_timestamps @@cache_asset_timestamps end # You can enable or disable the asset tag timestamps cache. # With the cache enabled, the asset tag helper methods will make fewer # expense file system calls. However this prevents you from modifying # any asset files while the server is running. # # ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false def self.cache_asset_timestamps=(value) @@cache_asset_timestamps = value end @@cache_asset_timestamps = true
booleanã®å¤ã§ãã
ããã«ã»ãã¿ã¼ã®ä¸ã«ä»åã®çããã³ã¡ã³ãã§æ¸ããã¦ã¾ããã
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false ããã°ã
æ¯å File.mtime(path) ãã¦ãããããã«ãªãã¾ãã
ãªã®ã§ãinitializersã¨ãã«ãé©å½ãªãã¡ã¤ã«ãä½ã£ã¦ã
# config/intializers/cache_asset_timestamp.rb ã¨ã ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
ã ãæ¸ãã¦ããã°ãproductionç°å¢ã§ãtouchãããã¿ã¤ã ã¹ã¿ã³ããæ´æ°ãããããã«ãªãã¾ãã
ã¡ãªã¿ã«ãdevelopmentç°å¢ã¯ãconfig/environments/development.rb ã§
config.cache_classes = false
ã«ãªã£ã¦ãã¨æãã¾ãããcache_classesãfalseã ã¨ã
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
ãå®è¡ãããã®ã§ãdevelopmentç°å¢ã§ã¯ä½ãããªãã¦ãã¿ã¤ã ã¹ã¿ã³ããæ´æ°ãããã£ã½ãã§ãã
jpmobileã使ã£ã¦ãau/softbankã§ããcontrollerå ã§ããã³ã¢çµµæåã«ãããã³ã°æ¸ã¿ã®utf8å¤ãå¾ãæ¹æ³
é常ã«ãããã«ããã¿ã¤ãã«ã§ããã
ã¦ã¼ã¶ãããã¹ããã©ã¼ã ã«çµµæåãå
¥ãã¦éã£ã¦ããã¨ãã®è©±ãã§ãã
以ä¸ã®ãããªã³ã¼ãããã£ãéã«ã
class HogeController < ApplicationController mobile_filter def hoge # ä¾ãã°ããã³ã¢ã®ãæ´ããã«å¯¾å¿ããçµµæåã¯ãjpmobileã® # before_filterãéã£ããactionã®æç¹ã§ã # docomo : \xEE\x98\xBE # au : \xEE\x92\x88 # softbank : \xEF\x81\x8A # ã¨ãªã£ã¦ãã end end
ãã®ã¾ã¾hogeã¢ã¯ã·ã§ã³ã®viewã§è¡¨ç¤ºãããªããjpmobileã®after_filterãããã£ã¦ã
docomo : \xF8\x9F (sjis)
au : \xF8\x9F (sjis)
softbank : \xEE\x98\xBE (utf8)
ã«ãªãã®ã§ãããhogeã¢ã¯ã·ã§ã³ã®ä¸ã§ãau/softbankã§ãdocomoã®å¤ãæã«å ¥ããã«ã¯ã©ããããããã§ããããã
ä¸å¿ãä¸è¨ã®æ¹æ³ã§æã«å ¥ãããã¨ãåºæ¥ãã®ã§ãã¡ã¢ã£ã¦ããã¾ãã
class HogeController < ApplicationController mobile_filter def hoge # strãå¤æãããæååã¨ãã㨠str = Jpmobile::Emoticon::utf8_to_unicodecr(str) str = Jpmobile::Emoticon::unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_DOCOMO, false) # ãã㧠str㯠# docomo : \xEE\x98\xBE # au : \xEE\x98\xBE # softbank : \xEE\x98\xBE # ã¨ãªãã¾ã end end
åç´ã«ãjpmobileã®after_filterãããã¦ããã ãã§ããã
unicodecr_to_externalã®3ã¤ç®ã®å¼æ°ãfalseã«ãã¦utf8-->sjiså¤æãè¡ãªããªãããã«ãã¦ãã¾ã
主ãã¼(primary key)ã® id ãä»»æã«æå®ãã¦ãcreateãã
# ruby script/console # æ®éã«æå®ãã¦ãç¡è¦ããã >> User.create(:id => 100) => #<User id: 1, created_at: "2010-12-13 02:47:03", updated_at: "2010-12-13 02:47:03"> # ãããã¯ã§æå®ãã㨠>> User.create do |u| ?> u.id = 100 >> end => #<User id: 100, created_at: "2010-12-13 02:48:22", updated_at: "2010-12-13 02:48:22">
使ãæ©ä¼ã¯ã»ã»ã»orz
sqlite3-ruby ã® version ã 1.2.x ã ã¨ãselect AS ã§ååãæå®ããã¨ãã« integer åã®ã«ã©ã ã®ã¯ãã string åã§åãã¦ãã件
sqlite3-ruby : version 1.2.5
$ rails testapp1 $ cd testapp1 $ ruby script/generate model user $ rake db:migrate $ ruby script/console >> User.create => #<User id: 1, created_at: "2010-11-25 08:49:43", updated_at: "2010-11-25 08:49:43"> >> User.first.id.class => Fixnum >> User.find(:first, :select => "id AS user_id").user_id.class => String # ããã
sqlite3-ruby : version 1.3.0
$ rails testapp2 $ cd testapp2 $ ruby script/generate model user $ rake db:migrate $ ruby script/console >> User.create => #<User id: 1, created_at: "2010-11-25 08:57:44", updated_at: "2010-11-25 08:57:44"> >> User.first.id.class => Fixnum >> User.find(:first, :select => "id AS user_id").user_id.class => Fixnum # OK
ã¾ã findã§:selectã使ããã¨ããããªãããã¾ãã¦AS使ããã¨ã¨ãã»ã¼ãªãã§ããã
ã¡ãªã¿ã« rails 㯠2.3.10
ãã©ã¡ã¼ã¿(params, query_paramters, path_parameters)åå¾æ¹æ³ã¡ã¢
params ã ã¨pathãã©ã¡ã¼ã¿ã¾ã§æ··ãã£ã¦ãã®ã§ãã¯ã¨ãªãã©ã¡ã¼ã¿ã ãåãæ¹æ³ãªã©ã調ã¹ã¦ã¿ãã¡ã¢ã
hoge ã³ã³ããã¼ã©ã« indexã¢ã¯ã·ã§ã³ãåå¨ãã¦ããç¶æ
ã§ã
config/routes.rb ã¯ä»¥ä¸ã¨ãã¾ãã
ActionController::Routing::Routes.draw do |map| map.edit_hoge '/hoge/:id/edit', :controller => 'hoge', :action => 'index' map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end
/hoge?aaa=1&bbb=2 ã«ã¢ã¯ã»ã¹ããéã®ãåãã©ã¡ã¼ã¿ããã·ã¥ãªã©ã®ä¸èº«ã¯ä»¥ä¸ã
{"aaa"=>"1", "bbb"=>"2", "action"=>"index", "controller"=>"hoge"} # params {"aaa"=>"1", "bbb"=>"2"} # request.query_parameters {"action"=>"index", "controller"=>"hoge"} # request.path_parameters Parameters: {"aaa"=>"1", "bbb"=>"2"} # log ã«åºåããããã¤
/hoge/1234/edit?aaa=1&bbb=2
{"aaa"=>"1", "bbb"=>"2", "action"=>"index", "id"=>"1234", "controller"=>"hoge"} # params {"aaa"=>"1", "bbb"=>"2"} # request.query_parameters {"action"=>"index", "id"=>"1234", "controller"=>"hoge"} # request.path_parameters Parameters: {"aaa"=>"1", "bbb"=>"2", "id"=>"1234"} # log ã«åºåããããã¤
ã¤ã¾ããrequest.path_parameters ã§ã¯ãURLã®ãã¹å
ã«å«ã¾ãã¦ãããã©ã¡ã¼ã¿ã®ã¿ãåå¾ã§ãã
request.query_parameters ã§ã¯ãã¯ã¨ãªãã©ã¡ã¼ã¿(ã¯ã¨ãªã¹ããªã³ã°ã®ãã©ã¡ã¼ã¿)ã®ã¿ãåå¾ã§ãã¾ãã
ã§ãparams ã¯ããã®ä¸¡æ¹ãåããã¨ã
development.log ãªã©ã«åºåããã¦ãã Parameters ã¯ç¹æ®ãªæãã§ã
path_parametersã¨query_parametersã®ä¸¡æ¹ãåºåããã¦ããã©ãactionã¨ãcontrollerã¯å
¥ã£ã¦ã¾ããã
ãã®logã®Parameters ã¨åãå¤ãå¾ãããããªå¤æ°ã¯è¦å½ãããªãã£ãã®ã§ã
å¿
è¦ã«ãªããã¨ããããã¯è¬ã ãã©ãåºåãã¦ããã§ãããç®æã調ã¹ã¦ã¿ã¾ããã
ãã¶ã actionpack ã® action_controller/base.rb ã®ä»¥ä¸ã®ã¡ã½ããã
def log_processing_for_parameters parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup parameters = parameters.except!(:controller, :action, :format, :_method) logger.info " Parameters: #{parameters.inspect}" unless parameters.empty? end
ã§ãfilter_parameters ã¯ãã°ããããªããã©ã¡ã¼ã¿ï¼passwordã¨ãï¼ãè¨å®ãã¦ãã°ã«ã¯ããªãããã«ãããã¨ãã§ãããã®ã£ã½ãã®ã§ãè¨å®ããã¦ããªããã°é¢ä¿ãªãã¦ã
åºæ¬çã«ãlog ã®ãParameters:ãã¯ãparamsããcontroller, action, format, _method ãé¤å¤ãã¦åºåãã¦ãããã®ã¨æã£ã¦ããããã§ãã
-
-
- -
-
ã2010-11-15 追è¨ã
query_parameters ã¯ããã¾ã§ãquery_stringãããã·ã¥åãããã®ã§ã
formããPOSTã§éä¿¡ããã¨ããªã©ã®ãã©ã¡ã¼ã¿ã¯å«ãã§ãã¾ããã§ããorz
ãªã®ã§ããã®éã«ãç´ç²(ï¼)ãªãã©ã¡ã¼ã¿ã ããå¾ãã«ã¯ã以ä¸ã®ããã«ãããããªãã®ããªã¨æãã¾ããã
query_params = params.dup
request.path_parameters.each_key{|k| query_params.delete(k)}
ãããªãã¨ããªãã¦ããä½ãè¯ãã¡ã½ãããªãå¤æ°ãªãããããããªæ°ããããã§ããã©ããèªåãç¥ããªãã ãã§ããã