數據內容對索引的影響
1 根據範式設計表
這個時候需要額外考慮的東西就是彙總表和緩存表。
2 考慮細節
這個時候,需要考慮的東西有以下這些:
- 存儲引擎:一般InnoDB
- 數據類型:一般考慮的點是大小,即是否貼合真實的數據
- 索引
- 主鍵(雖然在範式中有相關的主鍵和外鍵的概念,但是這裏的主鍵,說的是聚簇索引上主鍵的選擇)
- 索引的種類,哈希 or B-Tree / 等式查詢 or 範圍查詢
- 索引的排序,最左原則
2.1 主鍵的選擇
主鍵我們一般選擇id,然後自增,這對於存儲來說的確很友好,但是這樣僅僅是站在存儲的角度,查詢呢?我們很少使用主鍵做範圍查詢,相反,我們使用非聚簇索引做範圍查找的更多。這就是一個矛盾點。
即使是存在上面這樣的矛盾點,我還是建議使用傳統的id作爲主鍵。因爲非順序插入,對系統的影響更大。
那麼在確定主鍵是傳統的id情況下,我們需要從哪些角度綜合構建二級索引呢?
- 多列索引,即最左原則
- 覆蓋索引,這個可以算是一種很大程度上的優化,但是爲了覆蓋索引,而去覆蓋索引是愚蠢的,因爲要考慮在更新表期間表的鎖定情況
- 前綴索引,大字符串數據類型作爲索引時考慮
- 冗餘和重複索引,這個能說的地方就很多了
2.2 索引的維護
我們一般不去修改索引,因爲修改索引可能會造成表鎖,還有複製的情況下,各個備份數據庫的更新,簡單來說就是:麻煩。
這裏暫時不討論如果一定要修改表索引的話要怎麼做,就是單純的討論:如何維護好一份索引。
2.2.1 數據量小時沒有關注索引,後期體量大時,再來優化索引就很麻煩
這個大概是最經常踩的坑了,就是在早期沒有關注索引的情況,或者說只考慮了當時的業務情況,到了後期,隨着數據體量的上升,或者業務的修改,你需要去更新索引了,這個時候就GG了,因爲你根本不敢動索引。
可能有別的解決方案,但是僅僅站在這裏的角度去考慮,考慮使用多列索引,可以讓你在未來出現問題時,有一些緩衝的餘地。
2.2.2 查詢太多,修改索引怕顧此失彼
這個就是另一個方面的問題了,就是喜歡這裏設置一個查詢,那裏設置一個查詢,然後導致,要麼排查慢查詢時,滿世界找在哪裏調用了這張表,要麼就是改了索引後,引起之前查詢的效率下降,簡稱拆了東牆補西牆。
所以,如何管理代碼中對於查詢中索引的管理,一定要做好彙總工作,否則即使到了後期你直接修改索引,也可能會造成和之前查詢的矛盾,導致造成新的慢查詢。
所以在這裏建議,將查詢封裝在Model層中,然後再在service層中調用,這樣起碼可以讓你知道,針對當前表有哪些查詢,同時,多張表的關聯查詢應該是避免的,否則在數據庫層面,這些表的耦合就很難解開了。
2.3 數據內容對索引的影響
看下面這個情況:
- id,主鍵
- sex,索引
假設現在有這麼一種搜索情況:sex=1。
然後你發現還是很慢,查數據一看,全都是1,有索引和沒索引效果是一樣的,這個時候還需要索引嗎?
3 不滿足最左原則的情況下,如何讓MySQL使用最左原則?
就是一個小技巧,就是去湊查詢條件,即使一些字段查詢沒有效果也行,只要滿足最左原則,MySQL就會去走索引。
例子:
information_key(sex,name,age)
查詢爲:
where name="bob";
這樣的查詢肯定不會走 MySQL,所以最好的辦法就是湊:
sex in (1,0,0.5) and name="bob";
其中 sex 這一字段沒有任何含義,但是這樣強硬的湊上了最左原則,那麼MySQL就會走索引,比起全表掃描,效果會好很多。
4 大表排序
假設一張表有10000多行,這個時候你來一個查詢:
select <cols> from table_name order by keyDemo limit 99999,1;
這個時候,除非你是覆蓋索引,否則你的查詢效率都是低的,因爲MySQL需要先去過濾掉前面的那麼多條不符合條件的查詢,最後獲得一個數據。所以在這裏推薦一個技巧,來加速上面那種查詢:
select <cols> from table_name
inner join
(select id from table_name order by keyDemo limit 99999,1) as speedUp
on speedUp.id=table_name.id;