一:sql語句的小技巧
1.使用group by 分組查詢時,默認分組後,還會排序,可能會降低速度,在group by 後面增加 order by null 就可以防止排序。
2.有些情況下,可以使用連接來替代子查詢。因爲使用join,MySQL不需要在內存中創建臨時表。
如:select * from dept, emp where dept.deptno=emp.deptno;
// 替換成
select * from dept left join emp on dept.deptno=emp.deptno;
二:分表技術
1.什麼情況下需要分表?
(1) 如果一個表的每條記錄的內容很大,那麼就需要更多的IO操作,如果字段值比較大,而使用頻率相對比較低,可以將大字段移到另一張表中,當查詢不查大字段的時候,這樣就減少了I/O操作;
(2)如果表的數據量非常非常大,那麼查詢就變的比較慢;也就是表的數據量影響到查詢的性能;
(3)表中的數據本來就有獨立性,例如分別記錄各個地區的數據或者不同時期的數據,特別是有些數據常用,而另外一些數據不常用;
(4) 分表技術有兩種水平分割和垂直分割;
垂直分割
垂直分割是指數據表列的拆分,把一張表列比較多的表拆分爲多張表。垂直分割一般用於拆分大字段和訪問頻率低的字段,分離冷熱數據。
垂直分割比較常見:例如博客系統中的文章表,比如文章tbl_articles
(id, titile, summary, content, user_id, create_time),因爲文章中的內容content會比較長,放在tbl_articles中會嚴重影響表的查詢速度,所以將內容放到tbl_articles_detail(article_id, content),像文章列表只需要查詢tbl_articles中的字段即可。
垂直拆分的優點:可以使得行數據變小,在查詢時減少讀取的Block數,減少I/O次數。此外,垂直分區可以簡化表的結構,易於維護。
垂直拆分的缺點:主鍵會出現冗餘,需要管理冗餘列,並會引起join操作,可以通過在應用層進行join來解決。此外,垂直分區會讓事務變得更加複雜。
水平分割
水平拆分是指數據錶行數據的拆分,表的行數超過500萬行或者單表容量超過10GB時,查詢就會變慢,這時可以把一張的表的數據拆成多張表來存放。水平分表儘可能使每張表的數據量相當,比較均勻。
水平拆分會給應用增加複雜度,它通常在查詢是需要多個表名,查詢所有數據需要union操作。在許多數據庫應用中,這種複雜性會超過它帶來的優點。
因爲只要索引關鍵字不大,則在索引用於查詢時,表中增加2-3倍數據量,查詢時也就增加讀一個索引層的磁盤次數,所以水平拆分要考慮數據量的增長速度,根據實際情況決定是否需要對錶進行水平拆分。
水平分割最重要的是找到分割的標準,不同的表應根據業務找出不同的標準
-
用戶表可以根據用戶的手機號段進行分割如user151、user150、user153等,每個號段就是一張表
-
用戶表也可以根據用戶的id進行分割,加入分3張表user0,user1,user2,如果用戶的id%3=0就查詢user0表,
如果用戶的id%3=1就查詢user1表 -
對於訂單表可以按照訂單的時間進行分
三:讀寫分離技術
實現mysql讀寫分離的前提是我們已經將mysql主從複製配置完畢,讀寫分離實現方式:
(1)配置多數據源。
(2)使用mysql的proxy中間件代理工具,如mysql-proxy等
前提條件:必須要部署主從複製。
主從複製的原理
mysql的主從複製和讀寫分離兩者有着緊密的聯繫,首先要部署主從複製,只有主從複製完成了才能在此基礎上進行數據的讀寫分離。
讀寫分離的原理
讀寫分離就是隻在主服務器上寫,只在從服務器上讀。基本原理是讓主數據庫處理事務性insert、update、delete查詢,而從服務器處理select查詢。數據庫複製用來把事務性查詢導致的變更同步到從數據庫中。
四:索引優化
索引分類
-
普通索引:最基本的索引。
-
組合索引:多個字段上建立的索引,能夠加速複合查詢條件的檢索。
-
唯一索引:與普通索引類似,但索引列的值必須唯一,允許有空值。
-
組合唯一索引:列值的組合必須唯一。
-
主鍵索引:特殊的唯一索引,用於唯一標識數據表中的某一條記錄,不允許有空值,一般用primary key約束。
-
全文索引:用於海量文本的查詢,MySQL5.6之後的InnoDB和MyISAM均支持全文索引。由於查詢精度以及擴展性不佳,更多的企業選擇Elasticsearch。
索引優化
-
分頁查詢很重要,如果查詢數據量超過30%,MYSQL不會使用索引。
-
單表索引數不超過5個、單個索引字段數不超過5個。
-
字符串可使用前綴索引,前綴長度控制在5-8個字符。
-
字段唯一性太低,增加索引沒有意義,如:是否刪除、性別。
合理使用覆蓋索引,如下所示:
select login_name, nick_name from member where login_name = ?
login_name, nick_name兩個字段建立組合索引,比login_name簡單索引要更快。、
五:操作符優化
操作符<>優化
通常<>操作符無法使用索引,舉例如下,查詢金額不爲100元的訂單:
select id from orders where amount != 100;
如果金額爲100的訂單極少,這種數據分佈嚴重不均的情況下,有可能使用索引。鑑於這種不確定性,採用union聚合搜索結果,改寫方法如下:
(select id from orders where amount > 100)
union all
(select id from orders where amount < 100 and amount > 0)
OR優化
在Innodb引擎下or無法使用組合索引,比如:
select id,product_name from orders where mobile_no = '15321589999' or user_id = 100;
OR無法命中mobile_no + user_id的組合索引,可採用union,如下所示:
(select id,product_name from orders where mobile_no = '15321589999')
union
(select id,product_name from orders where user_id = 100);
此時id和product_name字段都有索引,查詢才最高效。
IN優化
IN適合主表大子表小,EXIST適合主表小子表大。由於查詢優化器的不斷升級,很多場景這兩者性能差不多一樣了。
嘗試改爲join查詢,舉例如下:
select id from orders where user_id in (select id from user where level = 'VIP');
採用JOIN如下所示:
select o.id from orders o left join user u on o.user_id = u.id where u.level = 'VIP';
不做列運算
通常在查詢條件列運算會導致索引失效,如下所示:
查詢當日訂單
select id from order where date_format(create_time,'%Y-%m-%d') = '2019-01-01';
date_format函數會導致這個查詢無法使用索引,改寫後:
select id from order where create_time between '2019-01-01 00:00:00'
Like優化
like用於模糊查詢,舉個例子(field已建立索引):
SELECT column FROM table WHERE field like '%keyword%';
這個查詢未命中索引,換成下面的寫法:
SELECT column FROM table WHERE field like 'keyword%';
去除了前面的%查詢將會命中索引,但是產品經理一定要前後模糊匹配呢?全文索引fulltext可以嘗試一下,但Elasticsearch纔是終極武器。
Join優化
join的實現是採用Nested Loop Join算法,就是通過驅動表的結果集作爲基礎數據,通過該結數據作爲過濾條件到下一個表中循環查詢數據,然後合併結果。如果有多個join,則將前面的結果集作爲循環數據,再次到後一個表中查詢數據。
驅動表和被驅動表儘可能增加查詢條件,滿足ON的條件而少用where,用小結果集驅動大結果集。
被驅動表的join字段上加上索引,無法建立索引的時候,設置足夠的Join Buffer Size。
禁止join連接三個以上的表,嘗試增加冗餘字段。
其他數據庫
作爲一名後端開發人員,不但要精通關係型數據庫,同時也要積極關注NoSQL非關係型數據庫,他們已經足夠成熟並被廣泛採用,能解決特定場景下的性能瓶頸。