有些一句簡單的sql看起來平平無奇,但是卻執行很慢,一般存在這麼幾種可能性:
針對sql執行慢,我們要做的首先就是定位出這些sql,然後再看這些sql是否正確建立並使用索引
慢查詢分析
mysql中自帶了慢查詢日誌的功能,使用show variables like '%slow_query_log%'
來查詢慢查詢日誌是否開啟
如下圖所示:
開啟慢查詢日誌
這種設定方式,只對當前資料庫生效,如果mysql重啟也會失效
如果要永遠生效,就必須修改mysql的配置檔案my.cnf,配置如下
slow_query_log =1 slow_query_log_file=/tmp/mysql_slow.log
分析sql運**況
使用explain 分析你sql的計畫,如下圖所示:
explain結果是基於資料庫表中現有資料的其中:table:輸出結果集的表
partitons:匹配的分割槽
type:表示表的連線型別
possible_keys:表示查詢時,可能使用到的索引
key:表示查詢時實際用到的索引
key_len:索引欄位的長度
ref:列與索引的比較
rows:大概估算的行數
filtered:按表條件過濾的行百分比
extra:執**況的描述和說明
這種情況下,由於大多數場合下還是比較快的,具有偶發性,一般來說這條sql的書寫本身沒什麼問題,更多的問題在於其他的外部原因導致的
資料庫在重新整理髒頁
要知道,我們往資料庫裡插入一條資料,或者更新一條資料的時候,資料庫會在記憶體中把相應欄位的資料給更新了,但是更新以後,資料不會立馬同步持久化到磁碟中去,而是把這些記錄寫到redo log日誌中去。等到空閒的時候,再通過redo log裡的日誌把最新的資料同步到磁碟中去。
不過容易造成乙個問題,就是redo log裡面的容量是有限的,如果資料庫一直很忙,更新又很頻繁,這個時候redo log被塞滿了,這個時候就只能暫停其他的操作,先把資料同步到磁碟中去,這個時候就導致我們平時執行很快的sql變得很慢。
拿不到鎖
我們執行的這個sql語句的時候,正好這條sql語句涉及到的表,被人加鎖了,我們暫時拿不到鎖,就只好等待。或者是表沒有加鎖,而是要使用到的某一行被加鎖了。
所以我們要判斷一下,是否是因為鎖問題導致的,可以使用show processlist這個來檢視當前的狀態(mysql)。
先假設乙個表,其中只有主鍵id和兩個普通欄位age和salary
沒用上索引create table `t` (
`id` int ( 11 ) not null,
`age` int ( 11 ) default null,
`salary` int ( 11 ) default null,
primary key ( `id` )
) engine = innodb;
因為我們在字段的左邊做了運算,導致在查詢的時候就用不上。select * from t where age-1=19;
資料庫選錯索引
例子:
我們知道主鍵索引和給主鍵索引時有區別的,也就是說如果走age這個欄位的索引的話最後會查詢到對應主鍵的值,然後再根據主鍵的值走主鍵索引,查詢到整行資料返回。select * from t where 1and age<100;
即就算age有索引,系統也不一定會走age這個欄位的索引,而是可以會直接掃瞄,掃瞄全表。
在執行這條語句的時候系統會進行**到底是走age的索引行數少,還是直接全表掃瞄的行數少,畢竟age索引找到主鍵後還需要通過主鍵索引來找整行資料。所以系統就通過索引的區分度來判斷:乙個索引上不同的值越多,意味著出現相同數值的索引越少,意味著索引的區分度越高。我們也把區分度稱之為基數,即區分度越高,基數越大。
即索引的基數越大就走索引查詢。
但系統通過取樣來判斷索引基數的大小,所以存在誤差判斷失誤。
即由於統計失誤,導致系統沒有走索引而是走了全表掃瞄,導致我們sql執行緩慢
可以通過sql語句強制走索引:select * from t force index(a) where 1and age<100;
也可以通過 show index from t ;來查詢索引的基數和實際是否符合,如果不符合可以重新統計:analyze table t如果出現這種情況,說明目前資料的承載能力已經達到了巔峰,因此我們需要使用一些資料庫的擴充套件手段來緩解mysql伺服器解決方案:讀寫分離
一般情況下,對資料庫而言,都是讀多寫少,壓力主要**於讀。針對這種情況,我們可以採用資料庫集群的方案,使用乙個庫作為主庫,負責寫入資料,其他庫作為從庫,負責讀資料,這樣可以減緩對資料庫的訪問壓力
實現方案
應用層解決方案
可以通過應用層對資料來源做路由來實現讀寫分離,比如使用springmvc+mybatis,可以將sql路由交給spring,通過aop或者annotation由**顯示的控制資料源。
缺點中介軟體解決方案
通過mysql的中介軟體做主從集群,比如使用mysql proxy、amoeba、atlas等中介軟體都能符合需求。
缺點索引優化
回表查詢:普通索引查詢到主鍵索引後,回到主鍵索引樹搜尋的過程,我們稱為回表查詢。資料拆分垂直拆分
將一張表拆分成多張表,其原則:
水平拆分
把一張表中的資料拆成多張表來存放,一般情況下使用取模的方式來進行拆分。
表的其他優化方案
一條sql 執行很慢的原因:
一直很慢:
資料庫選錯了索引
SQL取字段型別
存於每乙個資料庫的syscolumns表裡面的name就是列名,xtype就是資料型別,但是這個xtype是數字的,下面是數字和資料型別對應的關係 xtype 34 image xtype 35 text xtype 36 uniqueidentifier xtype 48 tinyint xtyp...
SQL2008 擷取字段函式
ltrim int轉字元 left abc 2 ab right abc 2 bc substring abc 1,2 ab 和delphi中的copy一樣 120 或者 20 yyyy mm dd hh mi ss 24h 121 或者 21 yyyy mm dd hh mi ss.mmm 24h...
sql中擷取字段資料的函式
今天遇到乙個做模糊查詢的問題,做模糊查詢時,要將做模糊查詢的資料第乙個數字給擷取掉。之前想在service中用for 迴圈 用startswith 做篩選,方案沒有通過,然後上網上搜取sql相關函式,找到了乙個方法 1 left s,n 函式返回字串s開始的最左邊n個字元。eg select lef...