where
,order by
和group by
的列上添加索引索引除了可以確保惟一的標記一條記錄,還能是MySQL服務器更快的從數據庫中獲取結果。索引在排序中的做用也很是大。mysql
Mysql的索引可能會佔據額外的空間,而且會必定程度上下降插入,刪除和更新的性能。可是,若是你的表格有超過10行數據,那麼索引就能極大的下降查找的執行時間。面試
強烈建議使用「最壞狀況的數據樣本」來測試MySql查詢,從而更清晰的瞭解查詢在生產中的行爲方式。sql
假設你正在一個超過500行的數據庫表中執行以下的查詢語句:數據庫
mysql>select customer_id, customer_name from customers where customer_id='345546'
上述查詢會迫使Mysql服務器執行一個全表掃描來得到所查找的數據。服務器
型號,Mysql提供了一個特別的Explain
語句,用來分析你的查詢語句的性能。當你將查詢語句添加到該關鍵詞後面時,MySql會顯示優化器對該語句的全部信息。微信
若是咱們用explain語句分析一下上面的查詢,會獲得以下的分析結果:架構
mysql> explain select customer_id, customer_name from customers where customer_id='140385'; +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | customers | NULL | ALL | NULL | NULL | NULL | NULL | 500 | 10.00 | Using where | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
能夠看到,優化器展現出了很是重要的信息,這些信息能夠幫助咱們微調數據庫表。首先,MySql會執行一個全表掃描,由於key列爲Null。其次,MySql服務器已經明確表示它將要掃描500行的數據來完成此次查詢。性能
爲了優化上述查詢,咱們只須要在customer_id
這一列上添加一個索引m便可:測試
mysql> Create index customer_id ON customers (customer_Id); Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0
若是咱們再次執行explain語句,會獲得以下結果:優化
mysql> Explain select customer_id, customer_name from customers where customer_id='140385'; +----+-------------+-----------+------------+------+---------------+-------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+-------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | customers | NULL | ref | customer_id | customer_id | 13 | const | 1 | 100.00 | NULL | +----+-------------+-----------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
從上述的輸出結果,顯然MySQL服務器會使用索引customer_id來查詢表格。能夠看須要掃描的行數爲1。雖然我只是在一個行數爲500的表格中執行這條查詢語句,索引在檢索一個更大的數據集的時候優化程度更加明顯。
有時候,你可能須要在查詢中使用or操做符進行比較。當or關鍵字在where子句中使用頻率太高的時候,它可能會使MySQL優化器錯誤的選擇全表掃描來檢索記錄。union子句能夠是查詢執行的更快,尤爲是當其中一個查詢有一個優化索引,而另外一個查詢也有一個優化索引的時候。
好比,在first_name
和last_name
上分別存在索引的狀況下,執行以下查詢語句:
mysql> select * from students where first_name like 'Ade%' or last_name like 'Ade%'
上述查詢和下面使用union合併兩條充分利用查詢語句的查詢相比,速度慢了許多。
mysql> select * from students where first_name like 'Ade%' union all select * from students where last_name like 'Ade%'
當查詢中存在前導通配符時,Mysql沒法使用索引。以上面的student表爲例,以下的查詢會致使MySQL執行全表掃描,及時first_name
字段上加了索引。
mysql> select * from students where first_name like '%Ade'
使用explain分析獲得以下結果:
mysql> explain select * from students where first_name like '%Ade' ; +----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | students | NULL | ALL | NULL | NULL | NULL | NULL | 500 | 11.11 | Using where | +----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+
如上所示,Mysql將掃描所有500行數據,這將使得查詢極其緩慢。
若是你正面臨着使用通配符查詢數據,可是並不想下降數據庫的性能,你應當考慮使用MySQL的全文檢索(FTS),由於它比通配符查詢快得多。除此之外,FTS還可以返回質量更好的相關結果。
添加一個全文檢索索引到student樣表上的語句以下:
mysql> alter table students add fulltext(first_name, last_name)'; mysql> select * from students where match(first_name, last_name) against ('Ade');
在上面的例子中,咱們針對搜索關鍵字Ade
指定了想要匹配的列(first_name, last_name)。若是查詢優化器如上語句的執行狀況,將獲得下面的結果:
mysql> explain Select * from students where match(first_name, last_name) AGAINST ('Ade'); +----+-------------+----------+------------+----------+---------------+------------+---------+-------+------+----------+-------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+----------+------------+----------+---------------+------------+---------+-------+------+----------+-------------------------------+ | 1 | SIMPLE | students | NULL | fulltext | first_name | first_name | 0 | const | 1 | 100.00 | Using where; Ft_hints: sorted | +----+-------------+----------+------------+----------+---------------+------------+---------+-------+------+----------+-------------------------------+
首先,規範化全部數據庫表,即便可能會有些損失。好比,若是你須要建立兩張表分別用來記錄customers和orders數據,你應當在order表上用顧客id引用顧客,而不是反過來。下圖顯示了沒有任何數據冗餘而設計的數據庫架構。
除此之外,對類似的值使用同一種數據類型類存儲。
MySQL支持各類數據類型,包括integer,float,double,date,datetime,varchar,text等。當設計數據庫表時,應當儘量使用可以知足特性的最短的數據類型。
好比,若是你在設計一個系統用戶表,而該用戶數量不會超過100我的,你就應該對user_ud使用'TINYINT'類型,該類型的取值範圍爲-128至128。若是一個字段須要存儲date型值,使用datetime類型比較好,由於在查詢的時候無需進行復雜的類型轉換。
當值全爲數字類型時,使用Integer。在進行計算時,Integer類型的值比文本類型的值速度更快。
NULL指該列沒有任何值。你應當儘量的避免這類型的值由於他們會損害數據庫結果。好比你須要得到數據庫中全部訂單金額的和,可是某個訂單記錄中金額爲null,若是不注意空指針,頗有可能致使計算結果出現異常。在某些狀況下,你可能須要爲列定義一個默認值。
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~