MySQL數據庫開發中的6個“避免”

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"關注"},{"type":"text","text":"“"},{"type":"text","marks":[{"type":"strong"}],"text":"Java後端技術全棧"},{"type":"text","text":"”**"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"回覆“面試”獲取全套大廠面試資料"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於近期工作涉及數據庫相關的操作較多,就根據自己的實戰經歷整理了一些數據庫開發的規範用法,利用6個“避免”來概括。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1、避免在數據庫中做運算"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有句話叫做“別讓腳趾頭想事情,那是腦瓜子的職責”,用在數據庫開發中,說的就是避免讓數據庫做她不擅長的事情。MySQL並不擅長數學運算和邏輯判斷,所以儘量不在數據庫做運算,複雜運算可以移到程序端CPU。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2、避免對索引列做運算"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有次,有位同事讓我看一條SQL,說是在前臺查詢很快,但是把SQL取出來,在數據庫中執行的時候,跑10分鐘都不出結果。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看了一下SQL,最後定位到一個視圖中的一個子查詢上面。該子查詢的SQL文本如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"SELECT  acinv_07.id_item ,\n        SUM(acinv_07.dec_endqty) dec_endqty\nFROM    acinv_07\nWHERE   acinv_07.fiscal_year * 100 + acinv_07.fiscal_period \n        = ( SELECT DISTINCT\n                   ctlm1101.fiscal_year * 100 + ctlm1101.fiscal_period\n                   FROM ctlm1101 WHERE flag_curr = 'Y'\n                   AND id_oprcode = 'acinv'\n                   AND acinv_07.id_wh = ctlm1101.id_table)\nGROUP BY acinv_07.id_item\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在acinv_07表上的列fiscal_year和列fiscal_period是有索引的。但是,如果對索引列進行運算,就會導致原本可以走索引的走不了索引。於是,動手改寫成如下SQL:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"SELECT    id_item ,\n                    SUM(dec_qty) dec_qty\n          FROM      dpurreq_03\n          GROUP BY  id_item\n        ) a ,\n        ( SELECT    a.id_item ,\n                    SUM(a.dec_endqty) dec_endqty\n          FROM      acinv_07 a ,\n                    ( SELECT DISTINCT\n                                ctlm1101.fiscal_year ,\n                                ctlm1101.fiscal_period ,\n                                id_table\n                      FROM      ctlm1101\n                      WHERE     flag_curr = 'Y'\n                                AND id_oprcode = 'acinv'\n                    ) b\n          WHERE     a.fiscal_year = b.fiscal_year\n                    AND a.fiscal_period = b.fiscal_period\n                    AND a.id_wh = b.id_table\n          GROUP BY  a.id_item\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再執行,4s鐘左右就可以跑出結果了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總的來說,寫SQL時,不到萬不得已,不要對索引列進行計算。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3、避免count(*)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在分頁查詢的時候,有的人總是習慣用select count("},{"type":"text","marks":[{"type":"italic"}],"text":")獲得總的記錄條數,實際上這不是一個高效的做法,因爲,之前獲得數據的時候已經查詢過一次了,select count("},{"type":"text","text":")相當於同一個語句查詢了兩次,對數據庫的開銷自然就大了,我們應當使用數據庫自帶的API,或者系統變量來完成這個工作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4、避免使用NULL字段"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"大家在數據庫表字段設計的時候,應該儘量都加上NOT NULL DEFAULT ''。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用NULL字段會產生很多不好的影響,例如:很難進行查詢優化、NULL列加索引,需要額外空間、含NULL複合索引無效……"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看下面的案例:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"數據初始化:\ncreate table table1 (\n    `id` INT (11) NOT NULL,\n    `name` varchar(20) NOT NULL\n)\ncreate table table2 (\n    `id` INT (11) NOT NULL,\n    `name`  varchar(20)\n)\ninsert into table1 values (4,\"zhaoyun\"),(2,\"zhangfei\"),(3,\"liubei\")\ninsert into table2 values (1,\"zhaoyun\"),(2, null)\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(1) NOT IN子查詢在有NULL值的情況下返回永遠爲空結果,查詢容易出錯"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"select name from table1 where name not in (select name from table2 where id!=1)\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/99/998aca5898ebd4126b320a20362708fd.jpeg","alt":"","title":"","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(2) 列值允許爲空,索引不存儲null值,結果集中不會包含這些記錄。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"select * from table2 where name != 'zhaoyun'\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/63/6324d7f33fd6a21b8c05a15f0b16d74a.jpeg","alt":"","title":"","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"select * from table2 where name != 'zhaoyun1'\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/80/80eac13b9e4ef10b084b80fb3bd6b3cc.jpeg","alt":"","title":"","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(3) 使用concat拼接時,首先要對各個字段進行非null判斷,否則只要任何一個字段爲空都會造成拼接的結果爲null"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"select concat(\"1\", null) from dual;\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/34/349c4d55aed777c2d1a4f390d6427037.jpeg","alt":"","title":"","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(4) 當計算count時候null column不會計入統計"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"select count(name) from table2;\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/bd/bd1ad69f0d533972fe6df7a7fe910551.jpeg","alt":"","title":"","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"5、避免select *"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule"},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用select *可能會返回不使用的列的數據。它在MySQL數據庫服務器和應用程序之間產生不必要的I/O磁盤和網絡流量。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果明確指定列,則結果集更可預測並且更易於管理。想象一下,當您使用select *並且有人通過添加更多列來更改表格數據時,將會得到一個與預期不同的結果集。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用select *可能會將敏感信息暴露給未經授權的用戶。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"6、避免在數據庫裏存圖片"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圖片確實是可以存儲到數據庫裏的,例如通過二進制流將圖片存到數據庫中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是,強烈不建議把圖片存儲到數據庫中!!!!首先對數據庫的讀/寫的速度永遠都趕不上文件系統處理的速度,其次數據庫備份變的巨大,越來越耗時間,最後對文件的訪問需要穿越你的應用層和數據庫層。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圖片是數據庫最大的殺手。一般來說數據庫都是存儲一個URL,然後再通過URL來調用圖片。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圖片,文件,二進制數這三樣東西慎重存儲到數據庫中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"推薦閱讀"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http://mp.weixin.qq.com/s?__biz=MzU4MDM3MDgyMA==&mid=2247492072&idx=1&sn=5ba44476be649f77c53a5312afc9d738&chksm=fd554903ca22c0151df9c2b94bbf80483eb546b9c9a4874978bc882aee106b60addf65250e3f&scene=21#wechat_redirect","title":null},"content":[{"type":"text","text":"【原創】SpringBoot快速整合Thymeleaf模板引擎"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http://mp.weixin.qq.com/s?__biz=MzU4MDM3MDgyMA==&mid=2247492058&idx=1&sn=3f030a8e85e8f65a9fc0ae7ac2a8993f&chksm=fd554931ca22c0274676b4c946cd8e5719bb92916d1e13196023837689289e9616b217b12850&scene=21#wechat_redirect","title":null},"content":[{"type":"text","text":"【原創】Spring Boot 集成Spring Data JPA的玩法"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http://mp.weixin.qq.com/s?__biz=MzU4MDM3MDgyMA==&mid=2247492059&idx=1&sn=2e9ed15b54ee7ce209048d5a75eb7d14&chksm=fd554930ca22c026d623769090b10abd33ebc9b44adfaef443efa078e7902ddf775fa9fba13c&scene=21#wechat_redirect","title":null},"content":[{"type":"text","text":"【原創】Spring Boot集成Mybatis的玩法"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/41/4120f5089df6d96b157afaf038417216.png","alt":"","title":"","style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章