數據內容對索引的影響--基於MySQL

數據內容對索引的影響

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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章