資料案例
N+1查詢問題
假設有如下的代碼骑疆,獲取10個客戶對象,并把客戶的郵編打印出來
clients = Client.limit(10)
clients.each do |client|
puts client.address.postcode
end
商品的代碼看起來很好,但問題在于查詢的總次數(shù)。上述代碼總共會執(zhí)行1(獲取10個客戶記錄)+10(分別獲取10個客戶的地址)= 11次查詢
N+1查詢的解決辦法
我們使用includes方法可以在取出10個客戶記錄的同時把這些記錄關聯(lián)的客戶地址一次性取出來活烙,這樣我們在訪問客戶地址時就不用再去執(zhí)行查詢語句了沃斤,因為第一次已經(jīng)把所需數(shù)據(jù)全部查詢出來了。
使用includes的代碼:
clients = Client.includes(:address).limit(10)
clients.each do |client|
puts client.address.postcode
end
和前面的 11 次查詢不同馋评,上述代碼只會執(zhí)行 2 次查詢:
SELECT * FROM clients LIMIT 10
SELECT addresses.* FROM addresses
WHERE (addresses.client_id IN (1,2,3,4,5,6,7,8,9,10))
構造案例
創(chuàng)建項目
rails _4.2.2_ new active_record_first -d=mysql
修改Gemfile文件诗芜,把gem源替換為source 'https://gems.ruby-china.org'
瞳抓,把gem 'mysql2'替換為gem 'mysql2', '~> 0.3.18'
把database.yml文件里面的數(shù)據(jù)庫密碼設置為本地mysql數(shù)據(jù)庫的密碼
cd active_record_first
bundle install
rake db:create
構造數(shù)據(jù)
需要兩張表,先創(chuàng)建兩張表的遷移文件
rails g migration CreateProducts
rails g migration CreateProductSecondTags
商品表 | products |
---|---|
image.png
|
image.png
|
商品二級標簽表 | product_second_tags |
---|---|
image.png
|
image.png
|
我們數(shù)據(jù)表不需要默認生成的id屬性伏恐,所以添加上id: false
我們使用rails默認的數(shù)據(jù)類型孩哑,定義就用t.string、t.integer的形式翠桦。
我們需要sql語句去定義類型時横蜒,定義就用t.column后面跟上sql數(shù)據(jù)類型定義。
數(shù)據(jù)表中的外鍵經(jīng)常用于查詢销凑,所以我們一般都會加上索引丛晌。
凡是ID字段,都用CHAR(36)的類型斗幼。
添加字段
rails g migration AddSecondTagIdToProducts
我們往products表添加一個新的字段TagID澎蛛,不過我們在遷移文件里面寫的時候遷移文件名是AddSecondTagIdToProducts,而不是AddSecondTagIDToProducts
填充數(shù)據(jù)表數(shù)據(jù)
添加模型文件
product模型需要訪問它關聯(lián)的數(shù)據(jù)表記錄蜕窿,所以數(shù)據(jù)關聯(lián)belongs_to需要寫在product模型文件谋逻。而我們目前不需要通過product_second_tag.products的訪問方式呆馁,所以product_second_tag不需要添加has_many數(shù)據(jù)關聯(lián)。
添加路由文件
添加控制器文件
Rails c模型下調試
注意:在rails c模型下毁兆,無論是代碼發(fā)生變更浙滤,或者我們在navicat里面插入新的數(shù)據(jù),都需要重新進入rails c控制臺才能生效气堕。
字段大小寫
我們在find_by中根據(jù)字段進行查找時纺腊,字段不區(qū)分大小寫
我們訪問查詢結果的字段時只有id(ID)屬性不區(qū)分大小寫,其他字段區(qū)分大小寫
N+1查詢問題
每次each送巡,都執(zhí)行一次sql查詢摹菠,所以下面執(zhí)行6次each盒卸,造成6次查詢(n次查詢)
使用includes的話骗爆,在得到products記錄的時候一次性把products關聯(lián)的二級標簽記錄都得到了。不管有沒有each里面的訪問都是兩條sql查詢
視圖文件下進行調試
遺留問題蔽介,為什么會出現(xiàn)CACHE摘投,我們就算在配置文件關閉緩存,添加如下代碼config.action_controller.perform_caching = false還是會有CACHE虹蓄。
可以看到犀呼,查詢ProductSecondTag執(zhí)行多條SQL語句
使用includes之后,就算不訪問關聯(lián)表薇组,也執(zhí)行2次查詢
我們只有操作數(shù)據(jù)時才會執(zhí)行查詢語句外臂,如下不進行訪問就沒有查詢語句
image.png
image.png
我們訪問數(shù)據(jù)的長度(就算不在視圖中<%= %>進行顯示),這時就執(zhí)行了查詢語句律胀。
image.png
image.png
我們在第一個語句并不執(zhí)行sql語句宋光。后面第一次使用數(shù)據(jù)時執(zhí)行兩條sql語句獲取到所有數(shù)據(jù)了。所有第二次炭菌、第三次罪佳。。黑低。第n次使用數(shù)據(jù)時都不再執(zhí)行sql查詢語句赘艳。
image.png
image.png
image.png
使用Git做版本控制
進入項目根目錄
.../active_record_first# git init
Initialized empty Git repository in /home/**********/active_record_first/.git/
git add -A
git commit -m "ActiveRecordFirst"
然后創(chuàng)建一個git倉庫
提交
git push -u https://github.com/xiaohuacc/active_record.git master
然后我們就可以在git倉庫看到我們提交的代碼了
在本地有時
取消提交(慎用)
我們有時從遠程倉庫拷貝代碼到本地之后,在本地提交了自己的多次修改克握,但是需求變動之后這些修改不需要了蕾管。我們可以取消這些修改,使用命令git reset --hard加上提交版本號菩暗;不過要注意我們使用該命令回退到指定A版本之后push到遠程倉庫掰曾,A版本后面的commit歷史就沒了----(無法通過commit歷史看到A版本之后的修改提交了)。一般這個命令要慎用勋眯,而且只用于回到自己最近一次本地的commit版本(該commit未push到遠程倉庫)婴梧。
我們在首次提交之后下梢,又在視圖文件添加了一下代碼。現(xiàn)在我們不要這些首次提交后的修改又很難一個個找到變動的地方改回來塞蹭,于是使用
首次提交孽江,使用git log
命令查看
commit bf2bd5a242d64564cd85383e17caa1af9ce786c8
Author: ***
Date: Sun Nov 27 14:59:05 2016 +0800
ActiveRecordFirst
然后又做了一下修改并提交了
git add .
git commit -m "測試git取消修改功能"
[master 77f455d] 測試git取消修改功能
2 files changed, 4 insertions(+), 4 deletions(-)
git log
commit 77f455d78967518c9db4f49812d739d3d0285224
Author: ***
Date: Sun Nov 27 15:11:53 2016 +0800
測試git取消修改功能
commit bf2bd5a242d64564cd85383e17caa1af9ce786c8
Author: ***
Date: Sun Nov 27 14:59:05 2016 +0800
ActiveRecordFirst
我們回到首次提交時的狀態(tài),去掉第二次提交的代碼修改
git reset --hard bf2bd5a242d64564cd85383e17caa1af9ce786c8
HEAD is now at bf2bd5a ActiveRecordFirst
然后回到IDE點擊YES重新加載項目代碼
然后我們git log
可以看到?jīng)]有第二次提交的log番电,這也意味著我們想要回到第二次的提交也是不行了岗屏。
commit bf2bd5a242d64564cd85383e17caa1af9ce786c8
Author: ***
Date: Sun Nov 27 14:59:05 2016 +0800
ActiveRecordFirst