- 論壇徽章:
- 0
|
Rails sql延遲加載和自帶緩存
Ruby代碼
- color_lot_manuallies = color_lot.color_lot_manuallies
- if color_lot_manuallies.size == 1
- end
復(fù)制代碼 引用- SELECT count(*) AS count_all FROM `color_lot_manuallies` WHERE (`color_lot_manuallies`.color_lot_id = 237)
復(fù)制代碼 當(dāng)有A has many B時(shí),a.bs.size并不是檢索出所有a.bs再求出size,而是直接用select count(*)來計(jì)算結(jié)果。這應(yīng)該是延遲加載,有點(diǎn)類似named_scope,但是并不是named_scope,named_scope的結(jié)果類是ActiveRecord::NamedScope::Scope,但是A.bs.class的結(jié)果是Array,這部分看了下源碼但是并沒有看懂。
所以當(dāng)我這樣寫的時(shí)候:
Ruby代碼- color_lot_manuallies = color_lot.color_lot_manuallies
- if color_lot_manuallies.size == 1
- end
- color_lot.color_lot_manuallies.each do |i|
- puts i.id
- end
復(fù)制代碼 引用- SQL (0.6ms) SELECT count(*) AS count_all FROM `color_lot_manuallies` WHERE (`color_lot_manuallies`.color_lot_id = 200)
- ColorLotManually Load (0.1ms) SELECT * FROM `color_lot_manuallies` WHERE (`color_lot_manuallies`.color_lot_id = 200)
復(fù)制代碼 這樣的話rails使用了延遲加載造成兩個(gè)sql不同,所以后面。color_lot.color_lot_manuallies再次使用時(shí),不會(huì)使用緩存的sql。
改成這樣:
Ruby代碼- color_lot_manuallies = color_lot.color_lot_manuallies.all
- if color_lot_manuallies.size == 1
- end
- color_lot.color_lot_manuallies.each do |i|
- puts i.id
- end
復(fù)制代碼 引用- ColorLotManually Load (0.1ms) SELECT * FROM `color_lot_manuallies` WHERE (`color_lot_manuallies`.color_lot_id = 198)
- CACHE (0.0ms) SELECT * FROM `color_lot_manuallies` WHERE (`color_lot_manuallies`.color_lot_id = 198)
復(fù)制代碼 加一個(gè)all,color_lot.color_lot_manuallies.all,這樣的話,后面再次調(diào)用時(shí),會(huì)使用rails的sql緩存。
Ruby代碼- #PurchaseOrder
- has_one :purchase_order_marketing, :dependent => :destroy
- has_many :purchase_invoices, :dependent => :destroy,:through => :purchase_order_marketing
- #PurchaseOrderMarketing
- has_many :purchase_invoices,:dependent => :destroy
-
- PurchaseOrder.first.purchase_invoices.all(:select => 'purchase_invoices.id')
復(fù)制代碼 引用- PurchaseOrder Load (0.2ms) SELECT * FROM `purchase_orders` LIMIT 1
- PurchaseInvoice Load (0.8ms) SELECT purchase_invoices.id FROM `purchase_invoices` INNER JOIN `purchase_order_marketings` ON `purchase_invoices`.purchase_order_marketing_id = `purchase_order_marketings`.id WHERE ((`purchase_order_marketings`.purchase_order_id = 13))
復(fù)制代碼 一條sql就完成了,真強(qiáng)大。
Ruby代碼- #article
- f sizes
- sizes = []
- art = self
- sf = art.article_secondary_feature
- size_group = SizeGroup.find_by_id(sf.size_groupid) if sf
- sizes = size_group.sizes if size_group
- return sizes
- end
復(fù)制代碼 Ruby代碼- ArticleMarketing.first.article.sizes.all(:select => 'id')
復(fù)制代碼 引用- ArticleMarketing Load (0.3ms) SELECT * FROM `article_marketings` LIMIT 1
- Article Load (0.8ms) SELECT * FROM `articles` WHERE (`articles`.`id` = 43)
- ArticleSecondaryFeature Load (0.7ms) SELECT `article_secondary_features`.* FROM `article_secondary_features` WHERE (`article_secondary_features`.article_id = 43)
- SizeGroup Load (0.6ms) SELECT * FROM `size_groups` WHERE (`size_groups`.`id` = 2) LIMIT 1
- Size Load (1.0ms) SELECT id FROM `sizes` WHERE (`sizes`.size_group_id = 2)
復(fù)制代碼 find和find_by_id
Ruby代碼- params[:root].classify.constantize.find_by_id(params[:id])
- params[:root].classify.constantize.find(params[:id])
復(fù)制代碼 引用- Opportunity Load (0.1ms) SELECT * FROM `opportunities` WHERE (`opportunities`.`id` = '126') LIMIT 1
- Opportunity Load (0.1ms) SELECT * FROM `opportunities` WHERE (`opportunities`.`id` = 126)
復(fù)制代碼 find_by_id的SQL多了一行l(wèi)imit 1,對(duì)于sql語句而言,有一點(diǎn)性能上的提高。不過有時(shí)候我們需要find來捕捉異常。如果能用find_by_id最好了。
都改成find_by_id
引用- Opportunity Load (0.1ms) SELECT * FROM `opportunities` WHERE (`opportunities`.`id` = '126') LIMIT 1
- CACHE (0.0ms) SELECT * FROM `opportunities` WHERE (`opportunities`.`id` = '126') LIMIT 1
復(fù)制代碼 這樣都有緩存了。rails的自帶的緩存是很脆弱的,B.find_by_id(a.id)方法變成a.b時(shí),這個(gè)緩存就不會(huì)用上。同樣前面的例子里改成
Ruby代碼- color_lot_manuallies = color_lot.color_lot_manuallies.all
- ColorLotManually.find_all_by_color_lot_id(color_lot.id)
復(fù)制代碼 rails自帶的緩存也不會(huì)用上。
關(guān)于||=緩存,參考
http://fuliang.javaeye.com/blog/827321
http://www.javaeye.com/topic/810957
但是有一點(diǎn),||=不會(huì)自動(dòng)清除或者更新,所以使用的時(shí)候還是要注意點(diǎn),可能會(huì)引起取值錯(cuò)誤,而且不會(huì)報(bào)錯(cuò)。
Ruby代碼- class PortOfDischage < ActiveRecord::Base
- def _name
- @_name ||= self.city
- end
- end
復(fù)制代碼 Ruby代碼- Reloading...
- => true
- >> p=PortOfDischage.first
- SQL (0.2ms) SET SQL_AUTO_IS_NULL=0
- PortOfDischage Load (21.2ms) SELECT * FROM `port_of_dischages` LIMIT 1
- PortOfDischage Columns (1.7ms) SHOW FIELDS FROM `port_of_dischages`
- +----+------------+-----------------+---------+---------+--------------------------------+--------------------------------+
- | id | ap_list_id | ap_marketing_id | city | country | created_at | updated_at |
- +----+------------+-----------------+---------+---------+--------------------------------+--------------------------------+
- | 1 | 2 | 2 | Piraeus | Greece | Thu Oct 07 07:10:21 +0800 2010 | Thu Oct 07 07:10:21 +0800 2010 |
- +----+------------+-----------------+---------+---------+--------------------------------+--------------------------------+
- 1 row in set
- >> p._name
- => "Piraeus"
- >> p.update_attribute(:city,'p')
- SQL (0.2ms) BEGIN
- ApMarketing Columns (43.0ms) SHOW FIELDS FROM `ap_marketings`
- ApMarketing Load (18.6ms) SELECT * FROM `ap_marketings` WHERE (`ap_marketings`.`id` = 2)
- PortOfDischage Update (45.5ms) UPDATE `port_of_dischages` SET `updated_at` = '2010-12-30 13:08:47', `city` = 'p' WHERE `id` = 1
- SQL (55.5ms) COMMIT
- => true
- >> p._name
- => "Piraeus"
- >> p.city
- => "p"
- >> p.reload
- PortOfDischage Load (0.7ms) SELECT * FROM `port_of_dischages` WHERE (`port_of_dischages`.`id` = 1)
- +----+------------+-----------------+------+---------+--------------------------------+--------------------------------+
- | id | ap_list_id | ap_marketing_id | city | country | created_at | updated_at |
- +----+------------+-----------------+------+---------+--------------------------------+--------------------------------+
- | 1 | 2 | 2 | p | Greece | Thu Oct 07 07:10:21 +0800 2010 | Thu Dec 30 13:08:47 +0800 2010 |
- +----+------------+-----------------+------+---------+--------------------------------+--------------------------------+
- 1 row in set
- >> p._name
- => "Piraeus"
復(fù)制代碼 |
|