1.創建數據和索引
1.創建索引測試表
1234567DROP TABLE IF EXISTS big_data;CREATE TABLE big_data(idintPRIMARY KEY NOT NULL AUTO_INCREMENT,name VARCHAR(16) DEFAULT NULL,ageint(11),email varchar(64)defaultnull)ENGINE=MYISAM DEFAULT CHARSET=utf8;注意:MYISAM存儲引擎不產生引擎事務,數據插入速度極快,為方便快速插入千萬條測試數據,等我們插完數據,再把存儲類型修改為InnoDB
2.創建存儲過程,插入數據
12345678CREATE PROCEDURE `insert_data_p`(IN num INT)BEGINDECLARE n INT DEFAULT 1;WHILE n <= num DOINSERT INTO big_data(name,age,email)values(concat('alex',n),rand()*50,concat('alex',n,'@qq.com'));setn=n+1;endwhile;ENd;
3.調用存儲過程,插入1000萬條數據(總耗時:382.614 sec)
1CALL insert_data_p(10000000);
4.此步驟可以忽略。修改引擎(執行耗時: 104.431 sec )
1ALTER TABLE `big_data` ENGINE=INNODB;
5.通過主鍵索引查詢(總耗時:0.012 sec)
1select*frombig_datawhereid = 8950000注意: 大家可能會發現一個問題: 第一次查詢時,會有點慢,而第二次查詢時就要比第一次快很多, why?
原因: 表引擎使用innodb.第一次查詢會走數據文件,第二次直接走buffer_pool(緩沖池),所以比直接查詢數據文件要快
6.為 name 字段創建普通索引(耗時:73.972 sec)
1CREATE INDEX index_name ON big_data (name);
2.組合索引的生效原則:
原則: 從前往后依次使用生效,如果中間某個索引沒有使用,那么斷點前面的索引部分起作用,斷點后面的索引沒有起作用;
3.正確使用索引
數據庫表中添加索引后確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,如果以錯誤的方式使用,則即使建立索引也會不奏效。
即使建立索引,索引也不會生效:
4.需要注意
123456789101.避免使用select*2.count(1)或count(列) 代替 count(*)3. 創建表時盡量時char代替 varchar4. 表的字段順序固定長度的字段優先5. 組合索引代替多個單列索引(經常使用多個條件查詢時)6. 使用連接(JOIN)來代替子查詢(Sub-Queries)7. 不要有超過5個以上的表連接(JOIN)8. 優先執行那些能夠大量減少結果的連接。9. 連表時注意條件類型需一致10.索引散列值不適合建索引,例:性別不適合
5.時間 (執行計划)
explain + 查詢SQL - 用於顯示SQL執行信息參數,根據參考信息可以進行SQL優化
1explainselect*frombig_datawhereage ='44'and name ='用戶8950000'
6.慢日志查詢
慢查詢日志
將mysql服務器中影響數據庫性能的相關SQL語句記錄到日志文件,通過對這些特殊的SQL語句分析,改進以達到提高數據庫性能的目的。
慢查詢日志參數:
12345long_query_time : 設定慢查詢的閥值,超出設定值的SQL即被記錄到慢查詢日志,缺省值為10sslow_query_log : 指定是否開啟慢查詢日志log_slow_queries : 指定是否開啟慢查詢日志(該參數已經被slow_query_log取代,做兼容性保留)slow_query_log_file : 指定慢日志文件存放位置,可以為空,系統會給一個缺省的文件host_name-slow.loglog_queries_not_using_indexes: 為使用索引的搜索是否記錄查看 MySQL慢日志信息
1234#.查詢慢日志配置信息 :show variables like'%query%';#.修改配置信息setglobal slow_query_log =on;查看不使用索引參數狀態:
1234# 顯示參數show variables like'%log_queries_not_using_indexes';# 開啟狀態setglobal log_queries_not_using_indexes =on;
7.大數據量分頁優化
1select*fromtb1 limit 3000000,10;優化方案:
一. 簡單粗暴,就是不允許查看這么靠后的數據,比如百度就是這樣的
最多翻到72頁就不讓你翻了,這種方式就是從業務上解決;
二.在查詢下一頁時把上一頁的行id作為參數傳遞給客戶端程序,然后sql就改成了
1select*fromtb1whereid>3000000 limit 10;這條語句執行也是在毫秒級完成的,id>300w其實就是讓mysql直接跳到這里了,不用依次在掃描全面所有的行
如果你的table的主鍵id是自增的,並且中間沒有刪除和斷點,那么還有一種方式,比如100頁的10條數據
1select*fromtb1whereid>100*10 limit 10;三.最后第三種方法:延遲關聯
我們在來分析一下這條語句為什么慢,慢在哪里。
1selectidfromtb1 limit 3000000,10;玄機就處在這個 * 里面,這個表除了id主鍵肯定還有其他字段 比如 name age 之類的,因為select * 所以mysql在沿着id主鍵走的時候要回行拿數據,走一下拿一下數據;
如果把語句改成
1selectidfromtb1 limit 3000000,10;你會發現時間縮短了一半;然后我們在拿id分別去取10條數據就行了;
語句就改成這樣了:
1selecttable.*fromtb1 innerjoin(selectidfromtb1 limit 3000000,10 )astmpontmp.id=table.id;這三種方法最先考慮第一種 其次第二種,第三種是別無選擇



