[TOC]
# 一個復雜查詢還是多個簡單的查詢
設計查詢的時候需要考慮的一個問題是,是否將一個復雜查詢分成多個簡單的查詢
在傳統的實現中,總是強調需要數據庫層完成盡可能多的工作,這樣做的邏輯在于以前總是認為網絡通信,查詢解析和優化是一件代價很高的事情
但是這樣對于mysql并不適用,mysql設計上讓連接和斷開都是很輕量級的
mysql內部每秒能夠掃描內存中百萬行數據,相比之下,mysql響應數據給客戶端就慢的多了.在其他條件相同的時候,使用盡可能少的查詢當然更好.但是有時候,一個大查詢分成多個小查詢還是很有必要的
# 切分查詢
有時候對于一個大查詢我們需要"分而治之",將大查詢切分成小查詢,每個查詢功能完全一樣,只完成一小部分,每次只返回一部分查詢結果
刪除舊的數據就是一個很好的例子.定期清除大量數據時,如果用一個大的語句一次性完成的話,則可能需要一次鎖住很多數據,占滿整個事務日志,耗盡系統資源,阻塞很多小的但重要的查詢.
將一個大的DELETE語句切分成多個較小的查詢可以盡可能小的影響mysql性能,同時還可以減少mysql復制的延遲.例如,我們需要每個月運行下面的查詢
~~~
mysql> delete from message where created < DATE_SUB(NOW(), INTERVAL 3 MONTH);
~~~
那么可以用類似下面的辦法來完成同樣的工作
~~~
rows_affected = 0
do {
rows_affected = do_query(
"DELETE FROM messages where created < DATE_SUB(NOW(), INTERVAL 3 MONTH)
limit 10000")
} while rows_affected>0
~~~
一次刪除一萬行數據對服務器來說是一個比較高效而且對服務器(Percona Toolkit中pt-archiver工具就可以安全簡單的完成這類工作)影響也最小的做法(如果是事務型引擎,很多時候小事務能夠更高效).
同時,需要注意的是,如果每次刪除數據后,都暫停一會兒再做下一次刪除,這樣也可以將服務器上原本一次性的壓力分散到一個很長的時間段,可以降低對服務器的影響,還可以大大減少刪除時鎖的持有時間
# 分解關聯查詢
很多高性能的應用都會對關聯查詢進行分解.簡單來說,可以對每一個表進行一次單表查詢,然后將結果在應用程序中進行關聯

有如下優勢
* 讓緩存的效率更高.許多應用程序可以方便地緩存單表查詢對應的結果對象.例如上面的查中的tag已經被緩存了,那么應用就可以跳過第一個查詢.再例如,應用中已經緩存了ID為123,567,9098的內容,那么第三個查詢中的IN()中就可以少幾個ID,另外,對mysql的查詢緩存來說,如果關聯的某個表發生了變化,那么就無法使用查詢緩存了,而拆分后,如果某個表很少改變,那么基于該表的查詢就可以重復利用查詢緩存的結果了
* 將查詢分解后,執行單個查詢可以減少鎖的競爭
* 在應用層做關聯,可以更容易對數據庫進行拆分,更容易做到高性能和可擴展
* 查詢本身效率也可能會有所提升,這個例子中,使用IN()代替關聯查詢,可以讓Mysql按照ID順序進行查詢,這可能比隨機的關聯要更高效,我們后續將詳細介紹這點
* 可以減少冗余記錄的查詢.在應用層做關聯查詢,意味著對于某條記錄應用只需要查詢一次,而在數據庫中做到關聯,則可能重復的訪問同一部分數據,從這點看,這樣的重構還可能會減少網絡和內存的消耗
* 更進一步,這樣做相當于在應用中實現了哈希關聯,而不是使用Mysql的嵌套循環關聯.某些場景哈希關聯的效率要高很多
當應用能夠方便的緩存單個查詢的結果的時候,當可以將數據分布帶不同mysql服務器上的時候,當能夠使用IN()的方式代替關聯查詢的時候,當查詢中使用同一個表的時候
- 書列表
- laravel框架關鍵技術
- 第一章 組件化開發與composer使用
- 簡介
- composer
- 添加路由組件
- 添加控制器模塊
- 添加模型組件
- 添加視圖組件
- 第三章 laravel框架中常用的php語法
- 匿名函數
- 文件包含
- 魔術方法
- 魔術常量
- 反射
- 后期靜態綁定
- traits
- 第四章 laravel框架中使用的HTTP協議基礎
- HTTP協議
- 數據庫
- 數據遷移
- 第六章 laravel框架中的設計模式
- IOC模式
- php核心技術與最佳實踐
- 第一章面向對象核心
- 反射
- 簡單ORM
- 異常和錯誤
- 接口
- 第二章,面向對象設計
- 設計原則
- 單一職責
- 接口隔離
- 開放封閉
- 替換原則
- 依賴倒置
- linux是怎么寫的呢?
- 第三章 正則表達
- 認識正則
- 第四章 php網絡技術應用
- HTTP協議詳解
- php和http相關函數
- 垃圾信息防御措施
- 現代操作系統
- 引論
- sql必知必會
- 限制結果
- 按位置排序
- where求職順序
- IN操作符
- like
- 函數
- group by
- 組合查詢
- 插入檢索出的數據
- 視圖
- 高性能mysql
- 第一章節 mysql架構與歷史
- mysql架構邏輯圖
- 連接與管理
- 優化與運行
- 讀寫鎖
- 鎖粒度
- 表鎖(table lock)
- 行級鎖(row lock)
- ACID
- 隔離級別
- 死鎖
- 隱式和顯式鎖定
- 多版本并發控制
- Innodb概覽
- 第四章節 Schema與數據類型優化
- 選擇優化的數據類型
- 日期和時間類型
- 標識列
- 特殊類型數據
- 表設計中的缺陷
- 范式
- 計數器表
- 第五章 創建高性能索引
- 索引基礎
- 索引類型
- 索引的優點
- 高性能索引策略
- 選擇合適的索引列順序
- 聚簇索引
- 順序的主鍵什么時候會造成更壞的后果
- 覆蓋索引
- 使用索引掃描來做排序
- 壓縮索引
- 冗余和重復索引
- 索引和鎖
- 支持多種過濾條件
- 什么是范圍條件
- 優化排序
- 維護索引和表
- 表損壞
- 減少索引和數據的碎片
- 第六章 查詢性能優化
- 掃描的行數和訪問類型
- 重構查詢方式
- 查詢執行的基礎
- 重構-改善既有代碼設計
- 第一章-重構
- 什么是重構
- 第一個案列
- 重構第一步
- 王垠博客
- 多態取代價格相關邏輯