日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

正确使用索引(sql优化),limit分页优化,执行计划,慢日志查询

發(fā)布時間:2025/6/17 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 正确使用索引(sql优化),limit分页优化,执行计划,慢日志查询 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

查看表相關命令

- 查看表結構
? ?desc 表名
- 查看生成表的SQL
? ?show?create?table?表名
- 查看索引
? ?show?index?from??表名

?

使用索引和不使用索引

由于索引是專門用于加速搜索而生,所以加上索引之后,查詢效率會快到飛起來。

# 有索引
mysql> select * from tb1 where name = 'zhangqiye'; +-----+-------------+---------------------+----------------------------------+---------------------+ | nid | name | email | radom | ctime | +-----+-------------+---------------------+----------------------------------+---------------------+ | 889 | zhangqiye | zhangqiye@live.com | 5312269e76a16a90b8a8301d5314204b | 2016-08-03 09:33:35 | +-----+-------------+---------------------+----------------------------------+---------------------+ 1 row in set (0.00 sec) ? # 無索引 mysql> select * from tb1 where email = 'zhangqiye@live.com'; +-----+-------------+---------------------+----------------------------------+---------------------+ | nid | name | email | radom | ctime | +-----+-------------+---------------------+----------------------------------+---------------------+ | 889 | zhangqiye | wupeiqi888@live.com | 5312269e76a16a90b8a8301d5314204b | 2016-08-03 09:33:35 | +-----+-------------+---------------------+----------------------------------+---------------------+ 1 row in set (1.23 sec)?

正確使用索引

數(shù)據(jù)庫表中添加索引后確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,如果以錯誤的方式使用,則即使建立索引也會不奏效。

即使建立索引,索引也不會生效的情況:

- like '%xx'
? ?select?*?from?tb1?where?name?like?'%cn';
- 使用函數(shù)
? ?select?*?from?tb1?where?reverse(name) =?'zhangqiye';
- or
? ?select?*?from?tb1?where?nid =?1?or?email =?'seven@live.com';
? ?特別的:當or條件中有未建立索引的列才失效,以下會走索引
? ? ? ? ? ?select?*?from?tb1?where?nid =?1?or?name?=?'seven';
? ? ? ? ? ?select?*?from?tb1?where?nid =?1?or?email =?'seven@live.com'?and?name?=?'zhangqiye'
- 類型不一致
? ?如果列是字符串類型,傳入條件是必須用引號引起來,不然...
? ?select?*?from?tb1?where?name?=?999;
- !=
? ?select?*?from?tb1?where?name?!=?'zhangqiye'
? ?特別的:如果是主鍵,則還是會走索引
? ? ? ?select?*?from?tb1?where?nid !=?123
- >
? ?select?*?from?tb1?where?name?>?'zhangqiye'
? ?特別的:如果是主鍵或索引是整數(shù)類型,則還是會走索引
? ? ? ?select?*?from?tb1?where?nid >?123
? ? ? ?select?*?from?tb1?where?num?>?123
-?order?by
? ?select?email?from?tb1?order?by?name?desc;
? ?當根據(jù)索引排序時候,選擇的映射如果不是索引,則不走索引
? ?特別的:如果對主鍵排序,則還是走索引:
? ? ? ?select?*?from?tb1?order?by?nid?desc;

- 組合索引最左前綴
? ?如果組合索引為:(name,email)
? ?name and email ? ? ??-- 使用索引
? ?name ? ? ? ? ? ? ? ??-- 使用索引
? ?email ? ? ? ? ? ? ? ?-- 不使用索引

?

其他注意事項

-?避免使用select *
-?count(1)或count(列) 代替 count(*)
-?創(chuàng)建表時盡量時 char 代替 varchar
-?表的字段順序固定長度的字段優(yōu)先
-?組合索引代替多個單列索引(經(jīng)常使用多個條件查詢時)
-?盡量使用短索引
-?使用連接(JOIN)來代替子查詢(Sub-Queries)
-?連表時注意條件類型需一致
-?索引散列值(重復少)不適合建索引,例:性別不適合

?

limit分頁

無論是否有索引,limit分頁是一個值得關注的問題

mysql大數(shù)據(jù)量使用limit分頁,隨著頁碼的增大,查詢效率越低下。

?

直接用limit?start,?count分頁語句

select?*?from?product?limit?start,?count
當起始頁較小時,查詢沒有性能問題,我們分別看下從10,?100,?1000,?10000開始分頁的執(zhí)行時間(每頁取20條),?如下:

select?*?from?product?limit?10,?20???0.016秒
select?*?from?product?limit?100,?20???0.016秒
select?*?from?product?limit?1000,?20???0.047秒
select?*?from?product?limit?10000,?20???0.094秒

我們已經(jīng)看出隨著起始記錄的增加,時間也隨著增大,?這說明分頁語句limit跟起始頁碼是有很大關系的,那么我們把起始記錄改為40w看下(也就是記錄的一般左右) ? ? ?select?*?from?product?limit?400000,?20?? 3.229秒

再看我們?nèi)∽詈笠豁撚涗浀臅r間
select?*?from?product?limit?866613,?20?? 37.44秒

難怪搜索引擎抓取我們頁面的時候經(jīng)常會報超時,像這種分頁最大的頁碼頁顯然這種時
間是無法忍受的。

從中我們也能總結出兩件事情:
1)limit語句的查詢時間與起始記錄的位置成正比
2)mysql的limit語句是很方便,但是對記錄很多的表并不適合直接使用。

?

對limit分頁問題的性能優(yōu)化方法

利用表的覆蓋索引來加速分頁查詢
我們都知道,利用了索引查詢的語句中如果只包含了那個索引列(覆蓋索引),那么這種情況會查詢很快。

因為利用索引查找有優(yōu)化算法,且數(shù)據(jù)就在查詢索引上面,不用再去找相關的數(shù)據(jù)地址了,這樣節(jié)省了很多時間。另外Mysql中也有相關的索引緩存,在并發(fā)高的時候利用緩存就效果更好了。

在我們的例子中,我們知道id字段是主鍵,自然就包含了默認的主鍵索引。現(xiàn)在讓我們看看利用覆蓋索引的查詢效果如何:

這次我們之間查詢最后一頁的數(shù)據(jù)(利用覆蓋索引,只包含id列),如下:
select?id?from?product?limit?866613,?20 0.2秒
相對于查詢了所有列的37.44秒,提升了大概100多倍的速度

那么如果我們也要查詢所有列,有兩種方法,一種是id>=的形式,另一種就是利用join,看下實際情況:

SELECT?*?FROM?product?WHERE?ID?>?=(select?id?from?product?limit?866613,?1)?limit?20
查詢時間為0.2秒,簡直是一個質(zhì)的飛躍啊,哈哈

另一種寫法SELECT?*?FROM?product?a?JOIN?(select?id?from?product?limit?866613,?20)?b?ON?a.ID?=?b.id查詢時間也很短,贊!

其實兩者用的都是一個原理嘛,所以效果也差不多


執(zhí)行計劃

explain + 查詢SQL - 用于顯示SQL執(zhí)行信息參數(shù),根據(jù)參考信息可以進行SQL優(yōu)化

如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B; +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+ | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 9 | NULL | | 2 | DERIVED | tb1 | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where | +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+

?

結果字段說明

id:查詢順序標識

select_type

查詢類型

SIMPLE ? ? ? ? ? ? ? ? 簡單查詢

PRIMARY ? ? ? ? ? ? ?最外層查詢

SUBQUERY ? ? ? ? ?映射為子查詢

DERIVED ? ? ? ? ? ? ?子查詢

UNION ? ? ? ? ? ? ? ? ? 聯(lián)合

UNION RESULT ? ?使用聯(lián)合的結果

?

table:正在訪問的表名

type

查詢時的訪問方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const

ALL (必須進行優(yōu)化) ? ? ? ? ? ?

全表掃描,對于數(shù)據(jù)表從頭到尾找一遍

select * from tb1;

特別的:如果有l(wèi)imit限制,則找到之后就不在繼續(xù)向下掃描

select * from tb1 where email = 'seven@live.com'

select * from tb1 where email = 'seven@live.com' limit 1;

雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個后就不再繼續(xù)掃描。

?

INDEX ? ? ? ? ??

全索引掃描,對索引從頭到尾找一遍

select nid from tb1;

?

RANGE ? ? ? ? ?

對索引列進行范圍查找

select * ?from tb1 where name < 'zhagsan';

between and

in

> ? >= ?< ? <= ?操作

注意:!= 和 > 符號

?

INDEX_MERGE ? ??

合并索引,使用多個單列索引搜索

select * ?from tb1 where name = zhangsan' or nid in (11,22,33);

?

REF ? ? ? ? ? ?

根據(jù)索引查找一個或多個值

select * ?from tb1 where name = 'seven';

?

EQ_REF ? ? ? ? ?

連接時使用primary key 或 unique類型

select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;

?

CONST ? ? ? ? ??

常量

表最多有一個匹配行,因為僅有一行,在這行的列值可被優(yōu)化器剩余部分認為是常數(shù),const表很快,因為它們只讀取一次。

select nid from tb1 where nid = 2 ;

?

SYSTEM ? ? ? ? ?

系統(tǒng)

表僅有一行(=系統(tǒng)表)。這是const聯(lián)接類型的一個特例。

select * from (select nid from tb1 where nid = 1) as A;

?

possible_keys:可能使用的索引

key?:真實使用的

key_len:MySQL中使用索引字節(jié)長度

rows

mysql估計為了找到所需的行而要讀取的行數(shù) ------ 只是預估值

?

慢日志查詢

MySQL的慢查詢?nèi)罩臼荕ySQL提供的一種日志記錄,它用來記錄在MySQL中響應時間超過閥值的語句,具體指運行時間超過long_query_time值的SQL,則會被記錄到慢查詢?nèi)罩局小ong_query_time的默認值為10,意思是運行10S以上的語句。默認情況下,Mysql數(shù)據(jù)庫并不啟動慢查詢?nèi)罩?#xff0c;需要我們手動來設置這個參數(shù),當然,如果不是調(diào)優(yōu)需要的話,一般不建議啟動該參數(shù),因為開啟慢查詢?nèi)罩緯蚨嗷蛏賻硪欢ǖ男阅苡绊?。慢查詢?nèi)罩局С謱⑷罩居涗泴懭胛募?#xff0c;也支持將日志記錄寫入數(shù)據(jù)庫表。

?

MySQL 慢查詢的相關參數(shù)解釋

slow_query_log ? ?:是否開啟慢查詢?nèi)罩?#xff0c;1表示開啟,0表示關閉。
log-slow-queries ?:舊版(5.6以下版本)MySQL數(shù)據(jù)庫慢查詢?nèi)罩敬鎯β窂?。可以不設置該參數(shù),系統(tǒng)則會默認給一個缺省的文件host_name-slow.log
slow-query-log-file:新版(5.6及以上版本)MySQL數(shù)據(jù)庫慢查詢?nèi)罩敬鎯β窂健?梢圆辉O置該參數(shù),系統(tǒng)則會默認給一個缺省的文件host_name-slow.log
long_query_time :慢查詢閾值,當查詢時間多于設定的閾值時,記錄日志。
log_queries_not_using_indexes:未使用索引的查詢也被記錄到慢查詢?nèi)罩局?#xff08;可選項)。
log_output:日志存儲方式。log_output='FILE'表示將日志存入文件,默認值是'FILE'。log_output='TABLE'表示將日志存入數(shù)據(jù)庫,
這樣日志信息就會被寫入到mysql.slow_log表中。MySQL數(shù)據(jù)<br>庫支持同時兩種日志存儲方式,配置的時候以逗號隔開即可,如:log_output='FILE,TABLE'。
日志記錄到系統(tǒng)的專用日志表中,要比記錄到文件耗費更多的系統(tǒng)資源,因此對于需要啟用慢查詢?nèi)罩?#xff0c;又需<br>要能夠獲得更高的系統(tǒng)性能,那么建議優(yōu)先記錄到文件。

?

開啟慢查詢

找到 MySQL 的配置文件 ,my.cnf (Windows?為 my.ini ),在 [mysqld]下增加下面幾行:

slow_query_log?=?1?? ? ? ? ? ? ? ? ? ? ? ? ?
long_query_time?=?2?? ? ? ? ? ? ? ? ? ? ? ? ??
slow_query_log_file?= /usr/slow.log ? ? ??
log_queries_not_using_indexes?=?1

重新啟動MySQL服務

?

MySQL 配置文件的位置

Windows:Windows 的配置文件為 my.ini,一般在 MySQL 的安裝目錄下或者 c:\Windows 下。

Linux:Linux 的配置文件為 my.cnf ,一般在 /etc 下。

?


?

識別圖中二維碼,領取python全套視頻

轉載于:https://www.cnblogs.com/IT-Scavenger/p/9192506.html

總結

以上是生活随笔為你收集整理的正确使用索引(sql优化),limit分页优化,执行计划,慢日志查询的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。