Re: [討論] SQL的指令優缺點消失
※ 引述《ripple0129 (perry tsai)》之銘言:
: 在看過一些複雜的SQL指令後,
: 覺得這是個難以維護的東西。
難以維護這個詞太籠統了,
你的難以維護是很多 join ? (其實對熟 sql 的來說這還非常簡單)
或是很多巢狀迴圈 ? (這也可以用 view 解決)
: 優點自然也是有的,
: 可以少寫不少程式碼。
: 而複雜的SQL指令不外乎Join了好幾個Table,
: Where了好幾種條件。
這樣聽起來很單純很好維護。
: 想請教各位大大對於SQL的應用上,
: 單純做CRUD然後給與對應的entity物件,
: 需要Join時就是Select Table出來,
: 之後再自行用程式碼拼裝。
痾... 你太輕忽 Database indexing 的能力了,
你自己拼裝,多了資料庫 io ,速度也不會比 indexed 後的資料用 sql 撈出來快。
indexing 早就在資訊界做了 N 年的研究,產生了 N 篇演算法的論文,
啥 B-Tree, B+ Tree 等等
: 還是下達花式SQL指令降低程式碼量好?
: 然後哪一種對資料庫有較輕的負擔?
當然是組 SQL 摟,
當你單一 Table 超過十幾萬筆、百萬筆,每次執行單一個 query
就將資料載入到 application 做運算,最後只拿幾十筆來用,你覺得這樣會快嗎?
: 反正規化的查詢速度優勢,
: 犧牲了正規後儲存空間以及降低了資料一致性,
儲存空間很便宜;
一致性要看該 case 重不重要。
最重要會做反正規化不外乎為了:
1. 增加速度
2. 降低資料庫使用的資源
: 且對於程式碼來說也降低維護性,
工程師都有程式或資料的潔癖,
有時候這些「降低維護性」的事可以避免你繞一大圈
增加一點維護性不算什麼
: 在現今環境來說值得嗎?
: 我個人的看法是維護性最高優先權,
一向都是看 case 為何。
像是你只是寫個簡單一兩萬內的小 case,
幫理髮店紀錄所有來過的客人的基本資料、消費紀錄
你是要用最原生的語言(像 php)直接快速寫完,
還是你還要抽介面、資料庫反正規化、用 MVC Framework ?
: 在維護性低的情形下,
: 後面加入的程式碼品質可能每況愈下。
: 程式碼品質不斷降低會造成資料庫的損耗加重。
兩者沒有直接關係
: 最後可能得不償失。
: 想了解我這樣的觀念是錯誤的嗎?
一點小經驗:
資料庫資源有限(license還很貴),不像 application 層可以橫向輕易地擴展,
資料庫是很難做多台機器 load balancing 的,
就算有的話後面還是共用同一顆硬碟。
又或者是只能用 replication 做讀寫分離這種程度而已。
因此的確需要對於資料庫資源使用有更多的考量
相反的 application 層大多可以輕易地橫向複製,
有些運算也真的可以不必在資料庫全部完成
然後資料庫的世界很廣,多去了解一下各種 index 適用於什麼樣的資料,如何精準地對
table 下 index;
資料正規化要如何設計,什麼是 entity、什麼是 relation 要先搞清楚
設計出來的 table schema 才會有彈性
另外整個架構還可以將一些全文檢索改用 elastic search,
一些常用的資料放在 redis cache,都是常見的做法
舉個實例:
以前我也遇過一張報表,是一張學期成績單,
除了要先找出該位學生,還要找出他這學期哪幾門課、教授是誰、學分數、分數、
有沒有 pass、有沒有抵免、有沒有教育學程、班排名、系排名、有沒有被 21
一個 sql 組出來大概超過百行吧(含一大堆子查詢)
但是程式可以怎麼設計呢?
每個學生修的課程、教授、學分數、分數、學期
先反正規化成一個 table(或view、indexed view)
一些單純設定檔的table放到redis cache,像是21規則、status code對應的文字等等
要用時再 application 層去組即可
然後每個學生的班排名、系排名也都反正規化到另外一張 table
最後只要簡單的 sql 就能查到要的資料,我的設計邏輯再留個文件
維護也簡單,只要確定底層的資料沒錯,在最上層只需要注重邏輯對不對就好
但是如果你要資料庫完全走正規化的路,
每次都是即時查詢,資料庫資源吃很重,且很耗時喔
一點心得分享
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.232.153.216
※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1476531830.A.BC1.html
※ 編輯: sing10407 (118.232.153.216), 10/15/2016 19:45:16
→
10/15 19:58, , 1F
10/15 19:58, 1F
→
10/15 19:58, , 2F
10/15 19:58, 2F
→
10/15 20:07, , 3F
10/15 20:07, 3F
推
10/15 20:42, , 4F
10/15 20:42, 4F
→
10/15 20:42, , 5F
10/15 20:42, 5F
→
10/15 20:42, , 6F
10/15 20:42, 6F
A(join): 1. Application 只需存取 db 一次
2. indexing 有做好就不太會吃太多資源
B(Application層做join):
1. N 張 table 代表要對 db 做 N 次 io
2. Application 要多寫一次 join 程式,且有淺在的效能問題
3. 好像也沒比較好維護
(後人要搞懂你邏輯,不如重寫下 sql join 快)
※ 編輯: sing10407 (118.232.153.216), 10/15/2016 20:55:31
推
10/15 21:14, , 7F
10/15 21:14, 7F
太多 join 不是問題,會慢的話就去檢查 index 有沒有設好;
若有子查詢就建議做成 view
如果 join 多到邏輯複雜、難以 debug,
就可以著手將一些 join 改成 view,這樣就可以做到主 sql 的精簡化,增加可維護性
→
10/15 21:22, , 8F
10/15 21:22, 8F
→
10/15 21:24, , 9F
10/15 21:24, 9F
正解
※ 編輯: sing10407 (118.232.153.216), 10/15/2016 21:33:12
※ 編輯: sing10407 (118.232.153.216), 10/15/2016 21:35:29
→
10/15 23:04, , 10F
10/15 23:04, 10F
→
10/15 23:43, , 11F
10/15 23:43, 11F
→
10/15 23:46, , 12F
10/15 23:46, 12F
→
10/15 23:46, , 13F
10/15 23:46, 13F
推
10/16 00:58, , 14F
10/16 00:58, 14F
→
10/16 00:58, , 15F
10/16 00:58, 15F
→
10/16 01:34, , 16F
10/16 01:34, 16F
→
10/16 01:34, , 17F
10/16 01:34, 17F
推
10/16 07:17, , 18F
10/16 07:17, 18F
→
10/16 07:17, , 19F
10/16 07:17, 19F
→
10/16 07:17, , 20F
10/16 07:17, 20F
推
10/16 09:00, , 21F
10/16 09:00, 21F
→
10/16 09:00, , 22F
10/16 09:00, 22F
→
10/16 09:00, , 23F
10/16 09:00, 23F
推
10/16 09:30, , 24F
10/16 09:30, 24F
推
10/16 09:47, , 25F
10/16 09:47, 25F
→
10/16 09:47, , 26F
10/16 09:47, 26F
→
10/16 09:47, , 27F
10/16 09:47, 27F
→
10/16 13:37, , 28F
10/16 13:37, 28F
→
10/16 13:40, , 29F
10/16 13:40, 29F
→
10/16 14:34, , 30F
10/16 14:34, 30F
推
10/16 15:33, , 31F
10/16 15:33, 31F
→
10/16 17:42, , 32F
10/16 17:42, 32F
推
10/16 20:55, , 33F
10/16 20:55, 33F
→
10/16 22:39, , 34F
10/16 22:39, 34F
→
10/18 00:03, , 35F
10/18 00:03, 35F
推
10/18 17:47, , 36F
10/18 17:47, 36F
推
10/25 10:30, , 37F
10/25 10:30, 37F
討論串 (同標題文章)