MySQL 性能調優之查詢優化


性能調優相關文檔書籍

http://dev.mysql.com/doc/refman/5.7/en/group-by-optimization.html

http://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.html

《MySQL性能調優與架構設計》

SQL查詢優化總結

  • 缺失索引,查詢速度差別是100倍:首先應考慮在 where 及 order by 涉及的列上建立索引

1 show index from mb_ransomrequestform;
2 ALTER TABLE mb_ransomrequestform ADD INDEX IDX_corporationid (corporationid);
3 drop index IDX_corporationid on mb_ransomrequestform;
View Code
  • 避免在 where 子句使用不能使用索引的操作符,比如!=、<>、like “%xx%”、or。否則將導致引擎放棄使用索引而進行全表掃描。

1)like “%xx%”改成like “xxx%”可以使用索引

mysql> select bill.billId from EE_PawnBill bill, EE_PawnerInfo pawner where bill.pawnerid = pawner.pawnerid and bill.businessstatus in (0,1,5) and bill.corporationid = 14077 and bill.status = 0 and pawner.username like '%薛建%' and (bill.printflag = '1' or bill.printstatus=0) order by bill.crtTime desc limit 15;

+----------------------+

| billId               |

+----------------------+

| DD330150020160421002 |

+----------------------+

1 row in set (2.58 sec)

 

mysql> select bill.billId from EE_PawnBill bill, EE_PawnerInfo pawner where bill.pawnerid = pawner.pawnerid and bill.businessstatus in (0,1,5) and bill.corporationid = 14077 and bill.status = 0 and pawner.username like '薛建%' and (bill.printflag = '1' or bill.printstatus=0) order by bill.crtTime desc limit 15;

+----------------------+

| billId               |

+----------------------+

| DD330150020160421002 |

+----------------------+

1 row in set (0.01 sec)
View Code

 

2)  select id from t where num=10 or num=20可以這樣查詢:select id from t where num=10 union all select id from t where num=20, 但不是所有or都不會使用索引,mysql自動優化:

desc select * from ee_pawncontinue c where c.CONTINUECODE="34010300013" or c.BILLID="00000618201205300002";

Using union(IDX_CONTINUECODE,index_billid); Using where
View Code

 

  • 減少不必要的子查詢,但是有時合適的子查詢比沒有子查詢更有效。

mysql> select count(*) from (select * from EE_PawnBill where corporationid = 2494) bill left join mb_ransomrequestform rrf on rrf.corporationid = 2494 and bill.pawncode=rrf.pawncode , EE_PawnerInfo pawner, EE_PawnRansom ransom where bill.pawnerid = pawner.pawnerid and bill.billid = ransom.billid and bill.printflag = 1 and ransom.corporationid = 2494;

+----------+

| count(*) |

+----------+

|    28798 |

+----------+

1 row in set (1.02 sec)

 

mysql> select count(*) from EE_PawnBill bill left join mb_ransomrequestform rrf on bill.corporationid = 2494 and rrf.corporationid = 2494 and bill.pawncode=rrf.pawncode , EE_PawnerInfo pawner, EE_PawnRansom ransom where bill.pawnerid = pawner.pawnerid and bill.billid = ransom.billid and bill.printflag = 1 and ransom.corporationid = 2494;

+----------+

| count(*) |

+----------+

|    28798 |

+----------+

1 row in set (0.32 sec)
View Code

 

  • Where條件:合適的where條件限定,不是越多越好,不是越少越好。應盡量避免全表掃描。

mysql> select count(*) from EE_PawnBill bill left join mb_ransomrequestform rrf on bill.corporationid = 2494 and rrf.corporationid = 2494 and bill.pawncode=rrf.pawncode , EE_PawnerInfo pawner, EE_PawnRansom ransom where bill.pawnerid = pawner.pawnerid and bill.billid = ransom.billid and bill.printflag = 1 and ransom.corporationid = 2494 and bill.corporationid = 2494;

+----------+

| count(*) |

+----------+

|    28798 |

+----------+

1 row in set (0.46 sec)

 

mysql> select count(*) from EE_PawnBill bill left join mb_ransomrequestform rrf on bill.corporationid = 2494 and rrf.corporationid = 2494 and bill.pawncode=rrf.pawncode , EE_PawnerInfo pawner, EE_PawnRansom ransom where bill.pawnerid = pawner.pawnerid and bill.billid = ransom.billid and bill.printflag = 1 and bill.corporationid = 2494;

+----------+

| count(*) |

+----------+

|    28798 |

+----------+

1 row in set (0.42 sec)

 

mysql> select count(*) from EE_PawnBill bill left join mb_ransomrequestform rrf on bill.corporationid = 2494 and rrf.corporationid = 2494 and bill.pawncode=rrf.pawncode , EE_PawnerInfo pawner, EE_PawnRansom ransom where bill.pawnerid = pawner.pawnerid and bill.billid = ransom.billid and bill.printflag = 1 and ransom.corporationid = 2494;

+----------+

| count(*) |

+----------+

|    28798 |

+----------+

1 row in set (0.27 sec)
View Code

 

  • 避免可能造成全表掃描的用法   

  • MySQL Max()函數的優化:MySQL Max() 函數是用來找出記錄集中最大值的記錄。

mysql> select max(pawner.pawnerId) from EE_PawnerInfo pawner where pawner.pawnerId like '1203400201605%';

+----------------------+

| max(pawner.pawnerId) |

+----------------------+

|   120340020160531001 |

+----------------------+

1 row in set (0.28 sec)

 

mysql> select pawner.pawnerId from EE_PawnerInfo pawner where pawner.pawnerId like '1203400201605%' order by pawner.pawnerId desc limit 1;

+--------------------+

| pawnerId           |

+--------------------+

| 120340020160531001 |

+--------------------+

1 row in set (0.06 sec)
View Code

 

提高mysql千萬級大數據SQL查詢優化30條經驗

http://www.jincon.com/archives/120/

30條經驗
1.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 whereorder by 涉及的列上建立索引。

2.應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:select id from t where num is null可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:select id from t where num=0

3.應盡量避免在 where 子句中使用!=<>操作符,否則引擎將放棄使用索引而進行全表掃描。

4.應盡量避免在 where 子句中使用or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:select id from t where num=10 or num=20可以這樣查詢:select id from t where num=10 union all select id from t where num=20

5.innot in 也要慎用,否則會導致全表掃描,如:select id from t where num in(1,2,3) 對於連續的數值,能用 between 就不要用 in 了:select id from t where num between 1 and 3

6.下面的查詢也將導致全表掃描:select id from t where name like '李%'若要提高效率,可以考慮全文檢索。

7. 如果在 where 子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變量,但優化程序不能將訪問計划的選擇推遲到運行時;它必須在編譯時進行選擇。然 而,如果在編譯時建立訪問計划,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:select id from t where num=@num可以改為強制查詢使用索引select id from t with(index(索引名)) where num=@num

8.應盡量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:select id from t where num/2=100應改為:select id from t where num=100*2

9.應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:select id from t where substring(name,1,3)='abc' ,name以abc開頭的id應改為:select id from t where name like 'abc%'

10.不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。

11.在使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應盡可能的讓字段順序與索引順序相一致。

12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:select col1,col2 into #t from t where 1=0這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:create table #t(...)

13.很多時候用 exists 代替 in 是一個好的選擇:select num from a where num in(select num from b)用下面的語句替換:select num from a where exists(select 1 from b where num=a.num)

14.並不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重復時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那么即使在sex上建了索引也對查詢效率起不了作用。

15. 索引並不是越多越好,索引固然可 以提高相應的 select 的效率,但同時也降低了 insertupdate 的效率,因為 insertupdate 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有 必要。

16. 應盡可能的避免更新 clustered 索引數據列,因為 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列,那么需要考慮是否應將該索引建為 clustered 索引。

17.盡量使用數字型字段,若只含數值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對於數字型而言只需要比較一次就夠了。

18.盡可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長字段存儲空間小,可以節省存儲空間,其次對於查詢來說,在一個相對較小的字段內搜索效率顯然要高些。

19.任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。

20.盡量使用表變量來代替臨時表。如果表變量包含大量數據,請注意索引非常有限(只有主鍵索引)。

21.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。

22.臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重復引用大型表或常用表中的某個數據集時。但是,對於一次性事件,最好使用導出表。

23.在新建臨時表時,如果一次性插入數據量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,為了緩和系統表的資源,應先create table,然后insert。

24.如果使用到了臨時表,在存儲過程的最后務必將所有的臨時表顯式刪除,先 truncate table ,然后 drop table ,這樣可以避免系統表的較長時間鎖定。

25.盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那么就應該考慮改寫。

26.使用基於游標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。

27. 與臨時表一樣,游標並不是不可使 用。對小型數據集使用 FAST_FORWARD 游標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括“合計”的例程通常要比使用游標執行的速度快。如果開發時 間允許,基於游標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。

28.在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句后向客戶端發送DONE_IN_PROC 消息。

29.盡量避免大事務操作,提高系統並發能力。

30.盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。30條經驗

 

MySQL性能調優之Query優化相關方法

MySQL Query Optimizer

>desc select * from table;

 

processlist

http://dev.mysql.com/doc/refman/5.7/en/show-processlist.html

>show processlist;

>show full processlist;

 

$ mysqladmin -h localhost  -u user -pPassword processlist

select count(*) from table bill  left join (select max(cont.enddate) as enddate, cont.billid f

select p.relatedId, p.picType, p.picName, p.picPath, p.entityId from table1 p

 

Explain and Profiling

MySQL可以通過EXPLAIN或DESC來查看並分析SQL語句的執行情況

set profiling=1;

select …;

show profiles;

set profiling=0;

show profile cpu,block io for query 1;

 

幾個分析慢查詢及優化的例子

mysql Copying to tmp table on disk 影響性能的解決方法

問題

set profiling=1;
select cont.billId, cont.pawnCode, cont.continueCode, cont.pawnerName, pawner.address as pawnerAddress, pawner.certificateName as pawnerCertName, pawner.certificateCode as pawnerCertCode, bill.pawnMoney as originalMoney, cont.pawnMoney, cont.beginDate, cont.endDate, cont.chargeMoney, cont.interestMoney, cont.shouldCharge, cont.disactCharge, cont.monthRate, cont.continueCharge, cont.interestRate, cont.shouldMoney, cont.status, cont.uploadStatus, cont.printStatus, crf.approveStatus as isPhone, cont.continueId from EE_PawnContinue cont left join mb_continuerequestform crf on crf.corpid = 2494 and cont.continueid=crf.continueid , EE_PawnBill bill, EE_PawnerInfo pawner where bill.pawnerid = pawner.pawnerid and bill.billid = cont.billid and bill.corporationid = 2494 and cont.printstatus = 1 and cont.status = 0  order by cont.continueCode desc limit 15;
show profiles;
set profiling=0;
show profile cpu,block io for query 1;
/* Affected rows: 0  已找到記錄: 32  警告: 0  持續時間 4 queries: 36.266 sec. */
View Code

分析

經過查資料發現mysql可以通過變量tmp_table_size和max_heap_table_size來控制內存表大小上限,如果超過上限會將數據寫到磁盤上,從而會有物理磁盤的讀寫操作,導致影響性能。

我們可以通過調整這兩個變量的值來提升性能(當然前提條件是mysql所在服務器有足夠的內存)。

首先可以通過下面語句查看當前的變量值:

SHOW VARIABLES LIKE 'max_heap_table_size%';

然后通過SET GLOBAL max_heap_table_size=522715200; 設置變量值為512M,你可以根據自己的情況設置合適的值;tmp_table_size變量的設置方法一樣。

現狀

mysql> SHOW VARIABLES LIKE 'max_heap_table_size%';
+---------------------+----------+
| Variable_name       | Value    |
+---------------------+----------+
| max_heap_table_size | 67108864 |
+---------------------+----------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'tmp_table_size%';
+----------------+--------+
| Variable_name  | Value  |
+----------------+--------+
| tmp_table_size | 262144 |
+----------------+--------+
1 row in set (0.00 sec)

mysql> show global status like 'created_tmp%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Created_tmp_disk_tables | 2270736  |
| Created_tmp_files       | 613427   |
| Created_tmp_tables      | 73485634 |
+-------------------------+----------+
3 rows in set (0.00 sec)
View Code

關於MySQL tmp_table_size   max_heap_table_size

http://www.t086.com/article/4813

tmp_table_size:

SET GLOBAL max_heap_table_size=134217728;  //128M

SET tmp_table_size=16777216; //16M

SET GLOBAL tmp_table_size=33554432; //32M

SET GLOBAL tmp_table_size=134217728;

測試環境:提高tmp_table_size到tmp_table_size最大值128M后,Copying to tmp table on disk的時耗降到了0.

但是Copying to tmp table的時間依然基本沒有改變,去掉了沒用到的select items后,時耗影響仍然不大,去掉的列中沒有text或者大varchar類型,因此應該影響不大。

 

Copying to tmp table太慢 解決方式

mysqladmin -h 192.168.1.155 -u root -p@*** processlist

登陸到后台,查詢一下 /opt/mysql/bin/mysqladmin processlist;
發現一個查詢狀態為: Copying to tmp table 而且此查詢速度非常慢,基本一分鍾左右才出來,后面是很多查詢,狀態為lock。

原因也是查詢涉及的中間數據太多導致,應該避免全表掃描等查詢。

 

MySQL Sending data導致查詢很慢的問題詳細分析

http://www.tuicool.com/articles/QzMZJb

Sending data: The thread is processing rows for a statement and also is sending data to the client.

這個數據中就可以看到MyISAM的Sending data比InnoDB的Sending data費時太多了。查看mysql文檔

http://dev.mysql.com/doc/refman/5.0/en/general-thread-states.html

Sending data

The thread is reading and processing rows for a SELECT statement, and sending data to the client. Because operations occurring during this this state tend to perform large amounts of disk access (reads), it is often the longest-running state over the lifetime of a given query.

Sending data是去磁盤中讀取select的結果,然后將結果返回給客戶端。這個過程會有大量的IO操作。你可以使用show profile cpu for query XX;來進行查看,發現MyISAM的CPU_system比InnnoDB大很多。至此可以得出結論是MyISAM進行表查詢(區別僅僅使用索引就可以完成的查詢)比InnoDB慢。

問題1:返回列的問題

經過一 一排查,最后定為到一個description的列上,這個列的設計為: `description` varchar(8000) DEFAULT NULL COMMENT '游戲描述', 可以看出,不返回description的時候,查詢時間只需要15s,返回的時候,需要216s, 兩者相差15倍.

有幾種解決方法:

1) 查詢時去掉description的查詢 ,但這受限於業務的實現,可能需要業務做較大調整

2) 增大Innodb buffer pool ,但由於Innodb buffer pool會根據查詢進行自動調整,因此如果gm_platform_info不是熱門表,作用也不是很明顯

3) 表結構優化 ,將descripion拆分到另外的表,這個改動較大,需要已有業務配合修改

問題2:order by + limit問題

select items.itemNum from ee_pawnitems items left join ee_pawnbill bills on items.billid = bills.billid left join ee_pawnerinfo info on bills.pawnerid = info.pawnerid left join kc_items_instock istock on items.billid = istock.billid and items.itemnum = istock.itemnum where 1 = 1 and bills.finishstatus = 1 and bills.printstatus=1 and bills.status = 0 and bills.corporationid = 2991 order by bills.pawnCode desc ;
/* Affected rows: 0  已找到記錄: 34,881  警告: 0  持續時間 1 query: 0.156 sec. (+ 0.297 sec. network) */
select items.itemNum from ee_pawnitems items left join ee_pawnbill bills on items.billid = bills.billid left join ee_pawnerinfo info on bills.pawnerid = info.pawnerid left join kc_items_instock istock on items.billid = istock.billid and items.itemnum = istock.itemnum where 1 = 1 and bills.finishstatus = 1 and bills.printstatus=1 and bills.status = 0 and bills.corporationid = 2991 order by bills.pawnCode desc limit 15;
/* Affected rows: 0  已找到記錄: 15  警告: 0  持續時間 1 query: 4.625 sec. */
View Code

改了order by的條件:

select bills.pawnCode, items.itemNum, info.userName, bills.businessStatus, items.itemName, bills.busiTypeId, bills.pawnMoney, items.stockStatus, bills.billId, istock.importTime, info.certificateType, info.certificateCode, istock.stockId, istock.itemId, istock.itemCode, bills.beginDate, bills.endDate, datediff( curdate(), bills.endDate) as diffDays, items.entityId from ee_pawnitems items left join ee_pawnbill bills on items.billid = bills.billid left join ee_pawnerinfo info on bills.pawnerid = info.pawnerid left join kc_items_instock istock on items.billid = istock.billid and items.itemnum = istock.itemnum where 1 = 1 and bills.finishstatus = 1 and bills.printstatus=1 and bills.status = 0 and bills.corporationid = 2991 order by bills.pawnCode desc limit 15;
/* Affected rows: 0  已找到記錄: 15  警告: 0  持續時間 1 query: 4.672 sec. */
select bills.pawnCode, items.itemNum, info.userName, bills.businessStatus, items.itemName, bills.busiTypeId, bills.pawnMoney, items.stockStatus, bills.billId, istock.importTime, info.certificateType, info.certificateCode, istock.stockId, istock.itemId, istock.itemCode, bills.beginDate, bills.endDate, datediff( curdate(), bills.endDate) as diffDays, items.entityId from ee_pawnitems items left join ee_pawnbill bills on items.billid = bills.billid left join ee_pawnerinfo info on bills.pawnerid = info.pawnerid left join kc_items_instock istock on items.billid = istock.billid and items.itemnum = istock.itemnum where 1 = 1 and bills.finishstatus = 1 and bills.printstatus=1 and bills.status = 0 and bills.corporationid = 2991 order by bills.crttime desc limit 15;
/* Affected rows: 0  已找到記錄: 15  警告: 0  持續時間 1 query: 0.047 sec. */
View Code

另參考:http://www.111cn.net/database/mysql/46425.htm

MySQL Order by 語句用法與優化詳解

http://www.jb51.net/article/38953.htm

以下情況order by不使用索引:

①SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
--order by的字段混合ASC和DESC
②SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
--用於查詢行的關鍵字與ORDER BY中所使用的不相同
③SELECT * FROM t1 ORDER BY key1, key2;
--對不同的關鍵字使用ORDER BY:

推測:在同時使用order by和limit時,MySQL進行了某些優化,將語句執行邏輯從"where——order by——limit"變成了"order by——limit——where",具體出現問題與否是與表中數據有關的。

select bill.pawnCode, coalesce(cont1.pawnMoney, bill.pawnMoney) as pawnMoney, bill.beginDate, bill.endDate, bill.businessStatus, pawner.userName as pawnerName, pawner.certificateName as pawnerCertName, pawner.certificateCode as pawnerCertCode, bill.status, bill.uploadStatus, bill.printStatus, bill.pawnerId, bill.billId from EE_PawnBill bill left join EE_PawnContinue cont1 on cont1.billid = bill.billid and cont1.active = 1 and cont1.status = 0, EE_PawnerInfo pawner where bill.pawnerid = pawner.pawnerid and bill.finishstatus = 1 and bill.corporationid in (888880001,3365,7225,14402,33863,1278,1274,7075) and bill.printstatus = 1 and bill.status = 0 and bill.businessstatus in (0, 1, 4) and bill.begindate >= '2016-06-01' and bill.begindate <= '2016-06-08' order by bill.billId desc limit 15;
/* Affected rows: 0  已找到記錄: 0  警告: 0  持續時間 1 query: 3.297 sec. */
select * from (select bill.pawnCode, coalesce(cont1.pawnMoney, bill.pawnMoney) as pawnMoney, bill.beginDate, bill.endDate, bill.businessStatus, pawner.userName as pawnerName, pawner.certificateName as pawnerCertName, pawner.certificateCode as pawnerCertCode, bill.status, bill.uploadStatus, bill.printStatus, bill.pawnerId, bill.billId from EE_PawnBill bill left join EE_PawnContinue cont1 on cont1.billid = bill.billid and cont1.active = 1 and cont1.status = 0, EE_PawnerInfo pawner where bill.pawnerid = pawner.pawnerid and bill.finishstatus = 1 and bill.corporationid in (888880001,3365,7225,14402,33863,1278,1274,7075) and bill.printstatus = 1 and bill.status = 0 and bill.businessstatus in (0, 1, 4) and bill.begindate >= '2016-06-01' and bill.begindate <= '2016-06-08' order by bill.billId desc) a limit 15;
/* Affected rows: 0  已找到記錄: 0  警告: 0  持續時間 1 query: 0.031 sec. */
View Code

問題3:單列索引 vs. 組合索引

只有主鍵索引或者多一個corpid索引,查詢時間一樣:竟然沒有使用corpId索引
select * from CorpKuaiMonthReportTwo corpkuaimo0_ where corpkuaimo0_.rptn='2016' and corpkuaimo0_.rptm='4' and corpkuaimo0_.corp_id=74536;
/* Affected rows: 0  已找到記錄: 1  警告: 0  持續時間 1 query: 0.438 sec. */

使用組合索引:對於條件的順序關系不大
select * from CorpKuaiMonthReportTwo corpkuaimo0_ where corpkuaimo0_.rptn='2016' and corpkuaimo0_.rptm='4' and corpkuaimo0_.corp_id=74536;
/* Affected rows: 0  已找到記錄: 1  警告: 0  持續時間 1 query: 0.031 sec. */
select * from CorpKuaiMonthReportTwo corpkuaimo0_ where corpkuaimo0_.corp_id=74536 and corpkuaimo0_.rptn='2016' and corpkuaimo0_.rptm='4';
/* Affected rows: 0  已找到記錄: 1  警告: 0  持續時間 1 query: 0.031 sec. */

 

MySQL query很快,network很慢的處理

select chanpayban0_.entityId as entityId28_, chanpayban0_.bankNo as bankNo28_, chanpayban0_.bankCode as bankCode28_, chanpayban0_.drctBankCode as drctBank4_28_, chanpayban0_.bankName as bankName28_, chanpayban0_.areaCode as areaCode28_, chanpayban0_.isSecBusiness as isSecBus7_28_, chanpayban0_.orderNum as orderNum28_, chanpayban0_.lastModifyTime as lastModi9_28_ from Chanpay_BankBranch chanpayban0_ where (exists (select 1 from Chanpay_AreaCode chanpayare1_ where chanpayare1_.codeMin+0<=chanpayban0_.areaCode+0 and chanpayare1_.codeMax+0>=chanpayban0_.areaCode+0 and chanpayare1_.areaCode='1100')) and chanpayban0_.bankNo='102';
/* Affected rows: 0  已找到記錄: 214  警告: 0  持續時間 1 query: 0.062 sec. (+ 1.516 sec. network) */

ALTER TABLE Chanpay_AreaCode ADD INDEX IDX_codeMin (codeMin);
ALTER TABLE Chanpay_AreaCode ADD INDEX IDX_codeMax (codeMax);
ALTER TABLE Chanpay_AreaCode ADD INDEX IDX_areaCode (areaCode);


select chanpayban0_.entityId as entityId28_, chanpayban0_.bankNo as bankNo28_, chanpayban0_.bankCode as bankCode28_, chanpayban0_.drctBankCode as drctBank4_28_, chanpayban0_.bankName as bankName28_, chanpayban0_.areaCode as areaCode28_, chanpayban0_.isSecBusiness as isSecBus7_28_, chanpayban0_.orderNum as orderNum28_, chanpayban0_.lastModifyTime as lastModi9_28_ from Chanpay_BankBranch chanpayban0_ where (exists (select 1 from Chanpay_AreaCode chanpayare1_ where chanpayare1_.codeMin+0<=chanpayban0_.areaCode+0 and chanpayare1_.codeMax+0>=chanpayban0_.areaCode+0 and chanpayare1_.areaCode='1000')) and chanpayban0_.bankNo='102'
;
/* Affected rows: 0  已找到記錄: 314  警告: 0  持續時間 1 query: 0.000 sec. (+ 0.125 sec. network) */

select chanpayban0_.entityId as entityId28_, chanpayban0_.bankNo as bankNo28_, chanpayban0_.bankCode as bankCode28_, chanpayban0_.drctBankCode as drctBank4_28_, chanpayban0_.bankName as bankName28_, chanpayban0_.areaCode as areaCode28_, chanpayban0_.isSecBusiness as isSecBus7_28_, chanpayban0_.orderNum as orderNum28_, chanpayban0_.lastModifyTime as lastModi9_28_ from Chanpay_BankBranch chanpayban0_ where (exists (select 1 from Chanpay_AreaCode chanpayare1_ where chanpayare1_.codeMin<=chanpayban0_.areaCode and chanpayare1_.codeMax>=chanpayban0_.areaCode and chanpayare1_.areaCode='1000')) and chanpayban0_.bankNo='102';
/* Affected rows: 0  已找到記錄: 314  警告: 0  持續時間 1 query: 0.000 sec. (+ 0.094 sec. network) */
View Code

優化:
1.    還是索引的缺失
2.    不要在sql中使用算術表達式:chanpayare1_.codeMin+0<=chanpayban0_.areaCode+0

 

Mysql索引介紹及常見索引的區別

Mysql索引概念:

說說Mysql索引,看到一個很少比如:索引就好比一本書的目錄,它會讓你更快的找到內容,顯然目錄(索引)並不是越多越好,假如這本書1000頁,有500也是目錄,它當然效率低,目錄是要占紙張的,而索引是要占磁盤空間的。

Mysql索引主要有兩種結構:B+樹和hash.

hash:hsah索引在mysql比較少用,他以把數據的索引以hash形式組織起來,因此當查找某一條記錄的時候,速度非常快.當時因為是hash結構,每個鍵只對應一個值,而且是散列的方式分布.所以他並不支持范圍查找和排序等功能.

B+樹:b+tree是mysql使用最頻繁的一個索引數據結構,數據結構以平衡樹的形式來組織,因為是樹型結構,所以更適合用來處理排序,范圍查找等功能.相對hash索引,B+樹在查找單條記錄的速度雖然比不上hash索引,但是因為更適合排序等操作,所以他更受用戶的歡迎.畢竟不可能只對數據庫進行單條記錄的操作.

Mysql常見索引有:

主鍵索引、唯一索引、普通索引、全文索引、組合索引

PRIMARY KEY(主鍵索引)  ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) UNIQUE(唯一索引)     ALTER TABLE `table_name` ADD UNIQUE (`column`)

INDEX(普通索引)     ALTER TABLE `table_name` ADD INDEX index_name ( `column` ) FULLTEXT(全文索引)      ALTER TABLE `table_name` ADD FULLTEXT ( `column` )

組合索引   ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )

Mysql各種索引區別:

普通索引:最基本的索引,沒有任何限制

唯一索引:與"普通索引"類似,不同的就是:索引列的值必須唯一,但允許有空值。

主鍵索引:它 是一種特殊的唯一索引,不允許有空值。

全文索引:僅可用於 MyISAM 表,針對較大的數據,生成全文索引很耗時好空間。

組合索引:為了更多的提高mysql效率可建立組合索引,遵循”最左前綴“原則。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM