MySQL 之 創建千萬數據測試


 

-- MySQL測試任務:使用存儲過程,往表中插入千萬級數據,根據索引優化速度
-- 1.使用索引查詢
-- 2.不使用索引查
-- 3.比較兩者查詢速度的差異

1.創建數據和索引

1.創建索引測試表
1
2
3
4
5
6
7
DROP TABLE IF EXISTS big_data;
CREATE TABLE big_data(
id  int  PRIMARY KEY NOT NULL AUTO_INCREMENT,
name VARCHAR(16) DEFAULT NULL,
age  int (11),
email varchar(64)  default  null
)ENGINE=MYISAM DEFAULT CHARSET=utf8;

 注意:MYISAM存儲引擎不產生引擎事務,數據插入速度極快,為方便快速插入千萬條測試數據,等我們插完數據,再把存儲類型修改為InnoDB

   2.創建存儲過程,插入數據
1
2
3
4
5
6
7
8
CREATE PROCEDURE `insert_data_p`(IN num INT)
BEGIN
DECLARE n INT DEFAULT 1;
WHILE n <= num DO
INSERT INTO big_data(name,age,email)values(concat( 'alex' ,n),rand()*50,concat( 'alex' ,n, '@qq.com' ));
set  n=n+1;
end  while ;
ENd; 
   3.調用存儲過程,插入1000萬條數據(總耗時:382.614 sec)
1
CALL insert_data_p(10000000);

  

   
    4.此步驟可以忽略。修改引擎(執行耗時: 104.431 sec  )
1
ALTER TABLE `big_data` ENGINE=INNODB;
   5.通過主鍵索引查詢(總耗時:0.012 sec)
1
select  from  big_data  where  id = 8950000

注意: 大家可能會發現一個問題: 第一次查詢時,會有點慢,而第二次查詢時就要比第一次快很多,  why?

原因: 表引擎使用innodb.第一次查詢會走數據文件,第二次直接走buffer_pool(緩沖池),所以比直接查詢數據文件要快

   6.為 name 字段創建普通索引(耗時:73.972 sec)
1
CREATE INDEX index_name ON big_data (name);

 2.組合索引的生效原則

  原則: 從前往后依次使用生效,如果中間某個索引沒有使用,那么斷點前面的索引部分起作用,斷點后面的索引沒有起作用;

 3.正確使用索引

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

4.需要注意

1
2
3
4
5
6
7
8
9
10
1.避免使用 select  *
2.count(1)或count(列) 代替 count(*)
3. 創建表時盡量時  char  代替 varchar
4. 表的字段順序固定長度的字段優先
5. 組合索引代替多個單列索引(經常使用多個條件查詢時)
6. 使用連接(JOIN)來代替子查詢(Sub-Queries)
7. 不要有超過5個以上的表連接(JOIN)
8. 優先執行那些能夠大量減少結果的連接。
9. 連表時注意條件類型需一致
10.索引散列值不適合建索引,例:性別不適合

5.時間 (執行計划)

  explain + 查詢SQL - 用於顯示SQL執行信息參數,根據參考信息可以進行SQL優化

1
explain  select  from  big_data  where  age = '44'  and  name = '用戶8950000'

 

6.慢日志查詢

 慢查詢日志 

   將mysql服務器中影響數據庫性能的相關SQL語句記錄到日志文件,通過對這些特殊的SQL語句分析,改進以達到提高數據庫性能的目的。

慢查詢日志參數:

1
2
3
4
5
long_query_time     :  設定慢查詢的閥值,超出設定值的SQL即被記錄到慢查詢日志,缺省值為10s 
slow_query_log      :  指定是否開啟慢查詢日志 
log_slow_queries    :  指定是否開啟慢查詢日志(該參數已經被slow_query_log取代,做兼容性保留) 
slow_query_log_file :  指定慢日志文件存放位置,可以為空,系統會給一個缺省的文件host_name-slow.log 
log_queries_not_using_indexes: 為使用索引的搜索是否記錄

查看 MySQL慢日志信息

1
2
3
4
#.查詢慢日志配置信息 :
show variables like  '%query%' ;
#.修改配置信息
set  global slow_query_log  =  on ;

查看不使用索引參數狀態:

1
2
3
4
# 顯示參數  
show variables like  '%log_queries_not_using_indexes' ;
# 開啟狀態
set  global log_queries_not_using_indexes  =  on ;

 7.大數據量分頁優化

1
select  from  tb1 limit 3000000,10;

優化方案:

一. 簡單粗暴,就是不允許查看這么靠后的數據,比如百度就是這樣的

最多翻到72頁就不讓你翻了,這種方式就是從業務上解決;

二.在查詢下一頁時把上一頁的行id作為參數傳遞給客戶端程序,然后sql就改成了

1
select  from  tb1  where  id>3000000 limit 10;

這條語句執行也是在毫秒級完成的,id>300w其實就是讓mysql直接跳到這里了,不用依次在掃描全面所有的行

如果你的table的主鍵id是自增的,並且中間沒有刪除和斷點,那么還有一種方式,比如100頁的10條數據

1
select  from  tb1  where  id>100*10 limit 10;

三.最后第三種方法:延遲關聯

我們在來分析一下這條語句為什么慢,慢在哪里。

1
select  id  from  tb1 limit 3000000,10;

玄機就處在這個 * 里面,這個表除了id主鍵肯定還有其他字段  比如 name  age  之類的,因為select  *  所以mysql在沿着id主鍵走的時候要回行拿數據,走一下拿一下數據;

如果把語句改成 

1
select  id  from  tb1 limit 3000000,10;

你會發現時間縮短了一半;然后我們在拿id分別去取10條數據就行了;

語句就改成這樣了:

1
select  table.*  from  tb1 inner  join  select  id  from  tb1 limit 3000000,10 )  as  tmp  on  tmp.id=table.id;

這三種方法最先考慮第一種 其次第二種,第三種是別無選擇


免責聲明!

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



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