優化table結構redis
#1 列數據類型儘可能使用數字類型,避免使用字符類型,後者不只會佔用較多存儲空間並且會下降查詢效率(逐字符比較);算法
#2 優先使用VARCHAR,變長字段存儲空間小,還能夠提高查詢效率;sql
#3 對須要常常做爲where條件出現的column添加索引,經過添加constraint設置爲unique key(自動添加索引);緩存
#4 對於單DB而言,primary key使用AUTO_INCREMENT的BIGINT是最合適的,自增類型的ID便於分頁和索引(UUID的key具備無序性,並且字符類型耗費資源);對於DB集羣而言,以DB自身的算法生成ID不能保證惟一性,因此須要引入一個全局的ID generator保證惟一性的同時提供較好的性能,Redis和ZooKeeper是比較好的選擇;另外經過給不一樣的DB或者App加入一個惟一的SN也能最大程度保證惟一性。架構
優化SQL語句併發
#1 對於查詢語句儘可能添加NO_LOCK標誌,提高DB併發量;分佈式
#2 篩選條件放置位置按優先級從高到低依次爲on, where, having,越到後面須要保存的數據和進行的計算就越多:memcached
#3 在where子句中避免使用[!=, <>, or, in, not in, %, like, is null, is not null],緣由是會致使DB引擎放棄使用index而進行全文掃描,推薦使用exist或者not exist;高併發
#4 若是某列的重複數據較多,則index不能發揮較好的性能,反而過多的索引還會下降insert和update的效率;性能
#5 對於涉及多張表的聯合查詢,依次將數據量最小的表按從右到左的順序放置,保證中間虛擬表只包含最少的數據;
#6 DB引擎解析一條SQL語句的流程
1 [8] SELECT [9] DISTINCT [11] TOP # <column list> 2 [1] FROM <left table> [3] <join type> JOIN <right table> [2] ON <join condition> 3 [4] WHERE <where condition> 4 [5] GROUP BY <group by list> 5 [6] WITH <CUBE | ROLLUP> 6 [7] HAVING <having condition> 7 [10] ORDER BY <order by list>;
對於sql中每個子句都會生成一張virtual table用於存儲中間數據,所以須要儘量的減小每一步中VT的數據,上述SQL語句的執行順序以下:
【1-3】:FROM子句中若是隻有一張表,則不作任何處理;若是有兩張表,則對其作笛卡爾積處理生成VT1;而後根據join condition執行ON子句進行篩選並生成VT2;接着根據join type(LEFT, RIGHT, INNER, OUTTER)執行JOIN子句生成VT3;若是有超過兩張表,則依次處理完前兩張表以後在VT3的基礎上繼續處理以後的表,直到全部的表都處理完最終生成VT4;SQL解釋器通常按照從右到左的順序處理表,所以須要保證越是靠右的表的數據量是越少的。
【4】:根據where condition執行WHERE子句,對中間表數據進行篩選並生成VT5。
【5】:根據group by list執行GROUP子句,對中間表進行分組並生成VT6。
【6】:根據CUBE仍是ROLLUP執行WITH子句,對分組結果進行彙總並生成VT7。
【7】:根據having condition執行HAVING子句,對分組結果進行篩選並生成VT8。
【8】:根據column list執行SELECT子句,對中間表進行數據映射並生成VT9。
【9】:執行DISTINCT子句,將重複的行從表中去除並生成VT10。
【10】:根據order by list執行ORDER BY子句,對中間表進行排序並生成VT11。
【11】:根據#(數量或者比例)執行TOP子句,從中間表中去除相應數據量結果並生成VT12。
按期查看SQL執行status
SQL server profiler,須要按期查看DB中超過某個執行時間限制的, 或者是資源佔用率超過某些限制的SQL語句;
讀寫分離
對於單庫DB設計而言,若是讀寫請求同時操做一個庫,勢必極大的下降DB性能;而通常狀況讀操做遠遠多於寫操做,這時候就能夠經過master-slave的設計,將同一個庫的數據作多個備份,寫操做僅針對master進行,讀操做在master和salve均可以進行;master按期將自身的數據更新到slave上,保證數據的最終一致性同時提高DB的QPS。
分庫分表
對於單庫多表而言,業務相關的數據儘可能放置於同一個庫1裏面(垂直切分,業務拆分),好比用戶A支付B元購買了C商品寄送到D地址,這樣能夠保證較好的讀取性能,這樣也能將事務限制在一個庫的範圍內;可是當庫1的某張表的數據記錄超過某個限制(單庫單表數據量在800萬條之內具備比較好的讀寫性能),須要另起一個庫2放置新增長的各個表的數據(水平切分),庫1和庫2具備相同的表組成,數據量增加的時候也以此類推,以後新的業務數據須要訪問和操做某個庫時,須要根據某種映射算法(key % n)選擇對應的庫進行數據讀寫,這個key必須是知足分佈式ID的全局惟一性;
在異地多活中心的架構中,分庫的設計能夠解決高併發訪問的問題,好比有100個手機庫存,若是放到一個庫裏,則全部併發都須要競爭同一把鎖,但若是將100個手機庫存平均分配到4個庫裏,每一個庫有25個庫存,則併發訪問能夠同時競爭四把鎖,極大提高了併發效率;另一種設計是將100個手機庫存維護在一個DB庫中,但使用redis等緩存基於窗口機制一次性獲取多個庫存到緩存中,好比redis-01預獲取0-24號庫存,則更新DB庫存爲75,redis-02預獲取25-49庫存,則更新DB庫存爲50,這樣的設計能夠減小較慢的DB鎖的競爭,而使用較快的cache鎖的競爭替代。
使用cache替代DB檢索
使用redis或者memcached做爲數據緩存