1. 程式人生 > 其它 >C# 實現傳送手機簡訊功能

C# 實現傳送手機簡訊功能

MySQL學習筆記和問題總結、效能優化

內連線

內連線(INNER JOIN) 簡單理解就是對兩個表求某種條件下的交集

需要解釋的地方是ON 關鍵字後的 JOIN 條件和 WHERE 關鍵字之後的篩選條件的執行計劃是一樣的,並且 WHERE 後的條件在實際執行中也會被轉化為 ON 的寫法,也就是最終都是在關聯的時候根據條件對資料進行過濾,而不是在關聯後所有結果集都出來了再通過 WHERE 來篩選

個人推薦在編寫 INNER JOIN 型別的查詢Sql時,必須的欄位可以寫到 ON 條件之後,非必須的欄位可以放到 WHERE 關鍵字之後使用動態Sql生成,這樣邏輯上更加清晰一點

左連線

左連線(LEFT JOIN)和 INNER JOIN 不同,LEFT JOIN 準確來說應該是左外連線(LEFT OUTER JOIN),連線時即使右表中沒有與左表對應的記錄時也會保留左表的記錄

需要注意的是 LEFT JOIN 中的 ON 和 WHERE 條件的執行計劃就不同了,ON 條件會在關聯的時候執行,而 WHERE 條件會在關聯後所有結果集都出來的情況下執行

分步查詢

任何聯合查詢都可以分解成多個單表查詢分步執行

舉個例子,如果要查詢多個指定分類的帖子,需要將型別表和帖子資訊表(分兩個表的情況下)進行連線,連線條件是型別id相等且是指定型別,這時候我們可以將其分解為兩個查詢,首先在型別表中查詢指定型別的主鍵集合,然後遍歷集合根據每個型別的主鍵去帖子表中再查詢該型別下的帖子集合

分步查詢有兩種實現方式,一種是直接使用程式碼控制,另一種是使用 ORM 框架實現(如Mybatis)

兩者的效能相當

使用程式碼控制

使用程式碼控制的實現方式優點是比較方便,可以對查詢出來的資料直接進行處理後封裝到 VO 中返回,減少了POJO物件,但是業務程式碼就會增多,後期維護的工作量也隨之增加

使用ORM框架實現(推薦)

使用ORM框架實現的優點自然就是業務程式碼簡潔明瞭,並且分解後的單表查詢也可以複用,但是POJO物件會增多,resultMap的配置也會增多,不過這樣又會使資料庫欄位與POJO類解耦,方便後期維護,比較推薦這種方式

查詢效能優化

關於JOIN

阿里巴巴開發手冊中規定三張表以上不能使用 JOIN(即使兩張表也要慎重考慮),做出這樣的規定是由阿里巴巴海量的資料規模所決定的,但對於一般公司來講可能完全達不到那樣的資料規模,這樣的限制對於較小規模的應用來說顯得不是那麼必要,但是個人認為還是有必要的

關於查詢分解

設計查詢的時候一個需要考慮的重要問題是,是否需要將一個複雜的查詢分成多個簡單的查詢,在傳統實現中,總是強調需要資料庫層完成儘可能多的工作,這樣做的邏輯在於以前總是認為網路通訊、查詢解析和優化是一件代價很高的事情,但是這樣的想法對於mysql並不適用,mysql從設計上讓連線和斷開連線都很輕量級,在返回一個小的查詢結果方面很高效,現代的網路速度比以前要快很多,無論是頻寬還是延遲,在某些版本的Mysql上,即使在一個通用伺服器上,也能夠執行每秒超過10萬的查詢,即使是一個千兆網絡卡也能輕鬆滿足每秒超過2000次的查詢,所以執行多個小查詢現在已經不是大問題了(摘自《高效能MySQL(第3版)》)

總結

儘量避免三張表及以上的 JOIN(某些情況下是避免不了的)

儘量避免巢狀查詢(並不是所有的巢狀查詢效能都很差,需要測試)

可以對關聯查詢進行分解(同第一條,某些關聯查詢是不能避免的)

此外,查詢的效能和索引的關係非常密切,設計一個好的索引能夠讓查詢效率提升幾個數量級

本節內容是針對一般情況而言的,給出的優化方式也都是建議,真實業務場景下的查詢往往需要進行測試才能驗證哪種方式更好,並且某些關聯查詢是不能進行分解的

不能分解的查詢舉例

查詢條件與多個表有關的分頁查詢

例如有兩個表,書籍資訊表和使用者書籍關係表,關係分為購買和收藏兩種,現在要分頁查詢使用者收藏的書籍中為科幻型別的書籍列表,查詢條件有使用者id、使用者書籍關係以及書籍的型別,思考一下怎麼做?

這時只能將兩表進行關聯查詢(進一步細分表的話甚至可能還要與書籍型別表進行關聯),為什麼呢?

假設現在分頁條件為獲取第一頁內容,頁大小為10,採用分步查詢的方式,首先通過查詢使用者書籍關係表獲得使用者收藏書籍的前10個,這時遍歷該列表去書籍資訊表中查詢書籍的資訊同時對型別進行篩選,結果發現已經查詢到的10個書中有兩個不是科幻型別的書,接下來怎麼做?重新去使用者書籍關係表裡查詢新的書再篩選湊夠10個?就算這樣做了,該查詢條件下到底有多少本書滿足條件?分頁資訊如何確定?

如果想要更加深入瞭解MySQL可以閱讀《高效能MySQL(第3版)》

常見問題

Mysql中只使用關鍵字 JOIN 的預設行為是內連線 INNER JOIN

表名 或 欄位名 加反引號,以防 表名 或 欄位名 為 mysql 關鍵詞,例如: orderuser

SELECT * from `order`
SELECT * from `user`

資料庫連線url的 zeroDateTimeBehavior=convertToNull 引數代表接受的時間格式錯誤時把錯誤的日期轉換為 null ,避免了 java.sql. SQLException: Cannot convert value '0000-00-00 00:00:00' from column XX to TIMESTAMP 異常,例:

spring.datasource.url=jdbc:mysql://localhost:3306/bingo?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull

開發和測試環境下的資料庫連線url後可加上引數 useSSL=false 避免程式發出 Establishing SSL connection without server's identity verification is not recommended. 警告,但是生產環境下必須使用SSL安全連線