天天看點

Mysql資料庫伺服器的CPU占用很高

mysql伺服器cpu占用很高

  1.  問題描述

  2.  問題原因

  查詢語句索引沒有命中導緻

  開始時的select

select

`province_name`,

`city_name`

from `phoneno_section`

where substring(?, phoneno_section_len) = phoneno_section

limit ?

咨詢說where中使用substring函數不行,修改函數為left,語句為

from `conf_phoneno_section`

where left(?, phoneno_section_len) = phoneno_section

  測試發現cpu占用還是很高,left函數中的參數是變量不是常量,再次修改select語句,指定left函數中的phoneno_section_len為固定值,cpu占用正常

  3.  mysql索引介紹

  ü  先舉個例子

  表a, 字段:  id(自增id),user(使用者名),pass(密碼),type(類型 0,1),

  索引: user + pass 建立聯合索引 ,user唯一索引,pass普通索引 ,type 普通索引

  ü  索引命中說明

  (1)select   *   from   a  where user = 't'  and pass = 'p'會命中user+pass的聯合索引

  (3)sql:  select   *   from   a  where user = 't'會命中user唯一索引

  (4)sql:  select   *   from   a  where pass = 'p'   不能命中任何索引

  (5)select  *  from  a where user = 't'  or   user= 'f' 相對于select  user,pass  from  a  where user = 't'  or   user= 'f'  會慢

  (6)select * from a where length(user) = 3 不能命中

  (7)user唯一索引 、type索引可以删除

  索引就是排序,目前的計算機技術和數學理論還不支援一次同時按照兩個關鍵字進行排序,即使是聯合索引,也是先按照最左邊的關鍵字先排,然後在左邊的關鍵字排序基礎上再對其他的關鍵字排序,是一個多次排序的結果。 是以,單表查詢,一次最多隻能命中一個索引,并且索引必須遵守最左字首。于是基于索引的結構和最左字首,像 or ,like '%%'都是不能命中索引的,而like 'aa%'則是可以命中的。

  無論是innodb還是myisam,索引隻記錄被排序的行的主鍵或者位址,其他的字段還是需要二次查詢,是以,如果查詢的字段剛好隻是包含在索引中,那麼索引覆寫将是高效的。

  如果所有的資料都一樣,或者基本一樣,那麼就沒有排序的必要了。像例子中的type隻有1或者0,選擇性是0.5,極低的樣紙,是以可以忽視,即使建立了,也是浪費空間,mysql在查詢的時候也會選擇丢棄。

  類似最左字首,查詢索引的時候,如果列被應用了函數,那麼在查詢的時候,是不會用到索引的。道理很簡單,函數運算已經改變了列的内容,而原始的索引是對列内容全量排序的。

  綜上所述,索引的幾個知識點:最左字首,索引覆寫,索引選擇性,列隔離在建立和使用索引的時候需要格外注意。

  4.  mysql索引無效場景補充

  ü  where子句的查詢條件裡有不等于号(where column!=...),mysql将無法使用索引

  ü  where子句的查詢條件裡使用了函數(如:where day(column)=...),mysql将無法使用索引,實驗中left函數是可以的,但是條件不能是變量,使用left函數且條件是變量,也無法使用索引,left函數之外是否有其它函數有待驗證

  ü  在join操作中(需要從多個資料表提取資料時),mysql隻有在主鍵和外鍵的資料類型相同時才能使用索引,否則即使建立了索引也不會使用

  ü  如果where子句的查詢條件裡使用了比較操作符like和regexp,mysql隻有在搜尋模闆的第一個字元不是通配符的情況下才能使用索引。比如說,如果查詢條件是like 'abc%',mysql将使用索引;如果條件是like '%abc',mysql将不使用索引。

  ü  在order by操作中,mysql隻有在排序條件不是一個查詢條件表達式的情況下才使用索引。盡管如此,在涉及多個資料表的查詢裡,即使有索引可用,那些索引在加快order by操作方面也沒什麼作用。

  ü  如果某個資料列裡包含着許多重複的值,就算為它建立了索引也不會有很好的效果。比如說,如果某個資料列裡包含了淨是些諸如“0/1”或“y/n”等值,就沒有必要為它建立一個索引。

  隻要建立了索引,除了上面提到的索引不會使用的情況下之外,其他情況隻要是使用在where條件裡,order by 字段,聯表字段,索引一般都是有效的。

最新内容請見作者的github頁:http://qaseven.github.io/