sql取字段中間幾位 為啥你這個sql怎麼慢呢

2021-10-18 00:04:46 字數 3395 閱讀 2867

有些一句簡單的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;

因為我們在字段的左邊做了運算,導致在查詢的時候就用不上。

資料庫選錯索引

例子:

select * from t where 1and age<100;
我們知道主鍵索引和給主鍵索引時有區別的,也就是說如果走age這個欄位的索引的話最後會查詢到對應主鍵的值,然後再根據主鍵的值走主鍵索引,查詢到整行資料返回。

即就算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...