最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

必須掌握的MySQL優(yōu)化方式!

2023-02-14 20:00 作者:橘子味派森  | 我要投稿

一、概念

在應(yīng)用的的開發(fā)過程中,由于初期數(shù)據(jù)量小,開發(fā)人員寫 SQL 語句時(shí)更重視功能上的實(shí)現(xiàn),但是當(dāng)應(yīng)用系統(tǒng)正式上線后,隨著生產(chǎn)數(shù)據(jù)量的急劇增長(zhǎng),很多 SQL 語句開始逐漸顯露出性能問題,對(duì)生產(chǎn)的影響也越來越大,此時(shí)這些有問題的 SQL 語句就成為整個(gè)系統(tǒng)性能的瓶頸,因此我們必須要對(duì)它們進(jìn)行優(yōu)化。

MySQL的優(yōu)化方式有很多,大致我們可以從以下幾點(diǎn)來優(yōu)化MySQL:

  • 從設(shè)計(jì)上優(yōu)化

  • 從查詢上優(yōu)化

  • 從索引上優(yōu)化

  • 從存儲(chǔ)上優(yōu)化

二、查看SQL執(zhí)行頻率

MySQL 客戶端連接成功后,通過 show [session|global] status 命令可以查看服務(wù)器狀態(tài)信息。通過查看狀態(tài)信息可以查看對(duì)當(dāng)前數(shù)據(jù)庫(kù)的主要操作類型。

--下面的命令顯示了當(dāng)前 session 中所有統(tǒng)計(jì)參數(shù)的值
show session status like 'Com_______'; ?-- 查看當(dāng)前會(huì)話統(tǒng)計(jì)結(jié)果
show global ?status ?like 'Com_______'; ?-- 查看自數(shù)據(jù)庫(kù)上次啟動(dòng)至今統(tǒng)計(jì)結(jié)果

show status like 'Innodb_rows_%’; ? ? ? -- 查看針對(duì)Innodb引擎的統(tǒng)計(jì)結(jié)果


三、定位低效率執(zhí)行SQL

可以通過以下兩種方式定位執(zhí)行效率較低的 SQL 語句。

? 慢查詢?nèi)罩?: 通過慢查詢?nèi)罩径ㄎ荒切﹫?zhí)行效率較低的 SQL 語句。

? show processlist:該命令查看當(dāng)前MySQL在進(jìn)行的線程,包括線程的狀態(tài)、是否鎖表等,可以實(shí)時(shí)地查看 SQL 的執(zhí)行情況,同時(shí)對(duì)一些鎖表操作進(jìn)行優(yōu)化。

定位低效率執(zhí)行SQL-慢查詢?nèi)罩?/strong>

-- 查看慢日志配置信息
show variables like '%slow_query_log%’;

-- 開啟慢日志查詢
set global slow_query_log=1;

-- 查看慢日志記錄SQL的最低閾值時(shí)間
show variables like 'long_query_time%’;

-- 修改慢日志記錄SQL的最低閾值時(shí)間
set global long_query_time=4;

定位低效率執(zhí)行SQL-show processlist

show processlist;


四、explain分析執(zhí)行計(jì)劃

通過以上步驟查詢到效率低的 SQL 語句后,可以通過 EXPLAIN命令獲取 MySQL如何執(zhí)行 SELECT 語句的信息,包括在 SELECT 語句執(zhí)行過程中表如何連接和連接的順序。

-- 準(zhǔn)備測(cè)試數(shù)據(jù)
create database mydb13_optimize;
use mydb13_optimize;

執(zhí)行sql腳本sql_optimize.sql添加數(shù)據(jù)


explain select * from user where uid = 1;


explain select * from user where uname = '張飛';



Explain分析執(zhí)行計(jì)劃-Explain 之 id

id 字段是 select查詢的序列號(hào),是一組數(shù)字,表示的是查詢中執(zhí)行select子句或者是操作表的順序。id 情況有三種:

1、id 相同表示加載表的順序是從上到下。

explain select * from user u, user_role ur, role r where u.uid = ur.uid and ur.rid = r.rid ;


2、 id 不同id值越大,優(yōu)先級(jí)越高,越先被執(zhí)行。

explain select * from role where rid = (select rid from user_role where uid = (select uid from user where uname = '張飛'))


3、 id 有相同,也有不同,同時(shí)存在。id相同的可以認(rèn)為是一組,從上往下順序執(zhí)行;在所有的組中,id的值越大,優(yōu)先級(jí)越高,越先執(zhí)行。

explain select * from role r , (select * from user_role ur where ur.uid = (select uid from user where uname = '張飛')) t where r.rid = t.rid ;


Explain分析執(zhí)行計(jì)劃-Explain 之 select_type

表示 SELECT 的類型,常見的取值,如下表所示:


Explain分析執(zhí)行計(jì)劃-Explain 之 type

type 顯示的是訪問類型,是較為重要的一個(gè)指標(biāo),可取值為:


結(jié)果值從最好到最壞以此是:system > const > eq_ref > ref > range > index > ALL

Explain分析執(zhí)行計(jì)劃-其他指標(biāo)字段

? Explain 之 table

顯示這一步所訪問數(shù)據(jù)庫(kù)中表名稱有時(shí)不是真實(shí)的表名字,可能是簡(jiǎn)稱,

? explain 之 rows

掃描行的數(shù)量。

? Explain 之 key

possible_keys : 顯示可能應(yīng)用在這張表的索引, 一個(gè)或多個(gè)。

key : 實(shí)際使用的索引, 如果為NULL, 則沒有使用索引。

key_len : 表示索引中使用的字節(jié)數(shù), 該值為索引字段最大可能長(zhǎng)度,并非實(shí)際使用長(zhǎng)度,在不損失精確性的前提下, 長(zhǎng)度越短越好 。


? Explain之 extra

其他的額外的執(zhí)行計(jì)劃信息,在該列展示 。


五、show profile分析SQL

Mysql從5.0.37版本開始增加了對(duì) show profiles 和 show profile 語句的支持。show profiles 能夠在做SQL優(yōu)化時(shí)幫助我們了解時(shí)間都耗費(fèi)到哪里去了。。

通過 have_profiling 參數(shù),能夠看到當(dāng)前MySQL是否支持profile:

select @@have_profiling;
set profiling=1; -- 開啟profiling 開關(guān);


通過profile,我們能夠更清楚地了解SQL執(zhí)行的過程。首先,我們可以執(zhí)行一系列的操作

show databases;

use mydb13_optimize;

show tables;

select * from user where id < 2;

select count(*) from user;

執(zhí)行完上述命令之后,再執(zhí)行show profiles 指令, 來查看SQL語句執(zhí)行的耗時(shí):

show profiles;


通過show profile for query query_id 語句可以查看到該SQL執(zhí)行過程中每個(gè)線程的狀態(tài)和消耗的時(shí)間:

show profile for query 8;


在獲取到最消耗時(shí)間的線程狀態(tài)后,MySQL支持進(jìn)一步選擇all、cpu、block io 、context switch、page faults等明細(xì)類型類查看MySQL在使用什么資源上耗費(fèi)了過高的時(shí)間。例如,選擇查看CPU的耗費(fèi)時(shí)間 :

show profile cpu for query 133; ?


在獲取到最消耗時(shí)間的線程狀態(tài)后,MySQL支持進(jìn)一步選擇all、cpu、block io 、context switch、page faults等明細(xì)類型類查看MySQL在使用什么資源上耗費(fèi)了過高的時(shí)間。例如,選擇查看CPU的耗費(fèi)時(shí)間 :


在獲取到最消耗時(shí)間的線程狀態(tài)后,MySQL支持進(jìn)一步選擇all、cpu、block io 、context switch、page faults等明細(xì)類型類查看MySQL在使用什么資源上耗費(fèi)了過高的時(shí)間。例如,選擇查看CPU的耗費(fèi)時(shí)間 :


六、trace分析優(yōu)化器執(zhí)行計(jì)劃

MySQL5.6提供了對(duì)SQL的跟蹤trace, 通過trace文件能夠進(jìn)一步了解為什么優(yōu)化器選擇A計(jì)劃, 而不是選擇B計(jì)劃


打開trace , 設(shè)置格式為 JSON,并設(shè)置trace最大能夠使用的內(nèi)存大小,避免解析過程中因?yàn)槟J(rèn)內(nèi)存過小而不能夠完整展示。

SET optimizer_trace="enabled=on",end_markers_in_json=on;
set optimizer_trace_max_mem_size=1000000;

執(zhí)行SQL語句 :

select * from user where uid < 2;

最后, 檢查
information_schema.optimizer_trace就可以知道MySQL是如何執(zhí)行SQL的 :

select * from information_schema.optimizer_trace\G;


索引是數(shù)據(jù)庫(kù)優(yōu)化最常用也是最重要的手段之一, 通過索引通??梢詭椭脩艚鉀Q大多數(shù)的MySQL的性能優(yōu)化問題。

? 數(shù)據(jù)準(zhǔn)備

create table `tb_seller` (
? ?`sellerid` varchar (100),
? ?`name` varchar (100),
? ?`nickname` varchar (50),
? ?`password` varchar (60),
? ?`status` varchar (1),
? ?`address` varchar (100),
? ?`createtime` datetime,
? ?primary key(`sellerid`)
);

索引是數(shù)據(jù)庫(kù)優(yōu)化最常用也是最重要的手段之一, 通過索引通??梢詭椭脩艚鉀Q大多數(shù)的MySQL的性能優(yōu)化問題。

? 數(shù)據(jù)準(zhǔn)備

insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('alibaba','阿里巴巴','阿里小店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('baidu','百度科技有限公司','百度小店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('huawei','華為科技有限公司','華為小店','e10adc3949ba59abbe56e057f20f883e','0','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('itcast','傳智播客教育科技有限公司','傳智播客','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('itheima','黑馬程序員','黑馬程序員','e10adc3949ba59abbe56e057f20f883e','0','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('luoji','羅技科技有限公司','羅技小店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');

索引是數(shù)據(jù)庫(kù)優(yōu)化最常用也是最重要的手段之一, 通過索引通??梢詭椭脩艚鉀Q大多數(shù)的MySQL的性能優(yōu)化問題。

insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('oppo','OPPO科技有限公司','OPPO官方旗艦店','e10adc3949ba59abbe56e057f20f883e','0','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('ourpalm','掌趣科技股份有限公司','掌趣小店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('qiandu','千度科技','千度小店','e10adc3949ba59abbe56e057f20f883e','2','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('sina','新浪科技有限公司','新浪官方旗艦店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('xiaomi','小米科技','小米官方旗艦店','e10adc3949ba59abbe56e057f20f883e','1','西安市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('yijia','宜家家居','宜家家居旗艦店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');

七、使用索引優(yōu)化

? 數(shù)據(jù)準(zhǔn)備

-- 創(chuàng)建組合索引
create index idx_seller_name_sta_addr on tb_seller(name,status,address);

? 避免索引失效應(yīng)用-全值匹配

該情況下,索引生效,執(zhí)行效率高。

explain select * from tb_seller where name='小米科技' and status='1' and address='北京市';

? 避免索引失效應(yīng)用-最左前綴法則

該情況下,索引生效,執(zhí)行效率高。

-- 最左前綴法則
-- 如果索引了多列,要遵守最左前綴法則。指的是查詢從索引的最左前列開始,并且不跳過索引中的列。
explain select * from tb_seller where name='小米科技'; -- 403

explain select * from tb_seller where name='小米科技' and status='1'; -- 410
explain select * from tb_seller where ?status='1' and name='小米科技'; -- 410
-- 違法最左前綴法則 , 索引失效:
explain select * from tb_seller where status='1'; -- nulll

-- 如果符合最左法則,但是出現(xiàn)跳躍某一列,只有最左列索引生效:
explain select * from tb_seller where name='小米科技' ?and address='北京市'; -- 403

? 避免索引失效應(yīng)用-其他匹配原則

該情況下,索引生效,執(zhí)行效率高。

-- 范圍查詢右邊的列,不能使用索引 。
explain select * from tb_seller where name='小米科技' and status >'1' and address='北京市’;

-- 不要在索引列上進(jìn)行運(yùn)算操作, 索引將失效。
explain select * from tb_seller where substring(name,3,2)='科技’

-- 字符串不加單引號(hào),造成索引失效。
explain select * from tb_seller where name='小米科技' and status = 1 ;

-- 1、范圍查詢右邊的列,不能使用索引 。
-- 根據(jù)前面的兩個(gè)字段name , status 查詢是走索引的, 但是最后一個(gè)條件address 沒有用到索引。
explain select * from tb_seller where name='小米科技' and status >'1' and address='北京市';

-- 2、不要在索引列上進(jìn)行運(yùn)算操作, 索引將失效。
explain select * from tb_seller where substring(name,3,2)='科技'

-- 3、字符串不加單引號(hào),造成索引失效。
explain select * from tb_seller where name='小米科技' and status = 1 ;

-- 4、盡量使用覆蓋索引,避免select *
-- 需要從原表及磁盤上讀取數(shù)據(jù)
explain select * from tb_seller where name='小米科技' ?and address='北京市'; ?-- 效率低

-- 從索引樹中就可以查詢到所有數(shù)據(jù)
explain select name from tb_seller where name='小米科技' ?and address='北京市'; ?-- 效率高
explain select name,status,address from tb_seller where name='小米科技' ?and address='北京市'; ?-- 效率高
-- 如果查詢列,超出索引列,也會(huì)降低性能。
explain select name,status,address,password from tb_seller where name='小米科技' ?and address='北京市'; ?-- 效率低

-- 盡量使用覆蓋索引,避免select *
-- 需要從原表及磁盤上讀取數(shù)據(jù)
explain select * from tb_seller where name='小米科技' ?and address='北京市'; ?-- 效率低

-- 從索引樹中就可以查詢到所有數(shù)據(jù)
explain select name from tb_seller where name='小米科技' ?and address='北京市'; ?-- 效率高
explain select name,status,address from tb_seller where name='小米科技' ?and address='北京市'; ?-- 效率高
-- 如果查詢列,超出索引列,也會(huì)降低性能。
explain select name,status,address,password from tb_seller where name='小米科技' ?and address='北京市'; ?-- 效率低

-- 用or分割開的條件, 那么涉及的索引都不會(huì)被用到。
explain select * from tb_seller where name='黑馬程序員' or createtime = '2088-01-01 12:00:00';
explain select * from tb_seller where name='黑馬程序員' or address = '西安市'; ?
explain select * from tb_seller where name='黑馬程序員' or status = '1'; ?

-- 以%開頭的Like模糊查詢,索引失效。
explain select * from tb_seller where name like '科技%'; -- 用索引
explain select * from tb_seller where name like '%科技'; -- 不用索引
explain select * from tb_seller where name like '%科技%';-- 不用索引
-- 彌補(bǔ)不足,不用*,使用索引列
explain select name from tb_seller where name like '%科技%';


-- ?1、如果MySQL評(píng)估使用索引比全表更慢,則不使用索引。
?-- 這種情況是由數(shù)據(jù)本身的特點(diǎn)來決定的
create index index_address on tb_seller(address);

explain select * from tb_seller where address = '北京市'; -- 沒有使用索引
explain select * from tb_seller where address = '西安市'; -- 沒有使用索引


-- ?2、is ?NULL , is NOT NULL ?有時(shí)有效,有時(shí)索引失效。
create index index_address on tb_seller(nickname);
explain select * from tb_seller where nickname is NULL; ?-- 索引有效
explain select * from tb_seller where nickname is not NULL; -- 無效

八、SQL優(yōu)化

? 大批量插入數(shù)據(jù)

create table `tb_user` (
?`id` int(11) not null auto_increment,
?`username` varchar(45) not null,
?`password` varchar(96) not null,
?`name` varchar(45) not null,
?`birthday` datetime default null,
?`sex` char(1) default null,
?`email` varchar(45) default null,
?`phone` varchar(45) default null,
?`qq` varchar(32) default null,
?`status` varchar(32) not null comment '用戶狀態(tài)',
?`create_time` datetime not null,
?`update_time` datetime default null,
?primary key (`id`),
?unique key `unique_user_username` (`username`)
);

當(dāng)使用load 命令導(dǎo)入數(shù)據(jù)的時(shí)候,適當(dāng)?shù)脑O(shè)置可以提高導(dǎo)入的效率。對(duì)于 InnoDB 類型的表,有以下幾種方式可以提高導(dǎo)入的效率:

1) 主鍵順序插入

因?yàn)镮nnoDB類型的表是按照主鍵的順序保存的,所以將導(dǎo)入的數(shù)據(jù)按照主鍵的順序排列,可以有效的提高導(dǎo)入數(shù)據(jù)的效率。如果InnoDB表沒有主鍵,那么系統(tǒng)會(huì)自動(dòng)默認(rèn)創(chuàng)建一個(gè)內(nèi)部列作為主鍵,所以如果可以給表創(chuàng)建一個(gè)主鍵,將可以利用這點(diǎn),來提高導(dǎo)入數(shù)據(jù)的效率。


-- 1、首先,檢查一個(gè)全局系統(tǒng)變量 'local_infile' 的狀態(tài), 如果得到如下顯示 Value=OFF,則說明這是不可用的
show global variables like 'local_infile';

-- 2、修改local_infile值為on,開啟local_infile
set global local_infile=1;

-- 3、加載數(shù)據(jù)
/*
腳本文件介紹 :
? ?sql1.log ?----> 主鍵有序
? ?sql2.log ?----> 主鍵無序
*/
load data local infile 'D:\\sql_data\\sql1.log' into table tb_user fields terminated by ',' lines terminated by '\n';

2 )、關(guān)閉唯一性校驗(yàn)

在導(dǎo)入數(shù)據(jù)前執(zhí)行 SET UNIQUE_CHECKS=0,關(guān)閉唯一性校驗(yàn),在導(dǎo)入結(jié)束后執(zhí)行SET UNIQUE_CHECKS=1,恢復(fù)唯一性校驗(yàn),可以提高導(dǎo)入的效率。

-- 關(guān)閉唯一性校驗(yàn)
SET UNIQUE_CHECKS=0;

truncate table tb_user;
load data local infile 'D:\\sql_data\\sql1.log' into table tb_user fields terminated by ',' lines terminated by '\n';

SET UNIQUE_CHECKS=1;

? 優(yōu)化insert語句

當(dāng)進(jìn)行數(shù)據(jù)的insert操作的時(shí)候,可以考慮采用以下幾種優(yōu)化方案:

-- 如果需要同時(shí)對(duì)一張表插入很多行數(shù)據(jù)時(shí),應(yīng)該盡量使用多個(gè)值表的insert語句,這種方式將大大的縮減客戶端與數(shù)據(jù)庫(kù)之間的連接、關(guān)閉等消耗。使得效率比分開執(zhí)行的單個(gè)insert語句快。

-- 原始方式為:
insert into tb_test values(1,'Tom');
insert into tb_test values(2,'Cat');
insert into tb_test values(3,'Jerry');


-- 優(yōu)化后的方案為 :

insert into tb_test values(1,'Tom'),(2,'Cat'),(3,'Jerry');

? 優(yōu)化insert語句

-- 在事務(wù)中進(jìn)行數(shù)據(jù)插入。
begin;
insert into tb_test values(1,'Tom');
insert into tb_test values(2,'Cat');
insert into tb_test values(3,'Jerry');
commit;

-- 數(shù)據(jù)有序插入
insert into tb_test values(4,'Tim');
insert into tb_test values(1,'Tom');
insert into tb_test values(3,'Jerry');
insert into tb_test values(5,'Rose');
insert into tb_test values(2,'Cat');


-- 優(yōu)化后
insert into tb_test values(1,'Tom');
insert into tb_test values(2,'Cat');
insert into tb_test values(3,'Jerry');
insert into tb_test values(4,'Tim');
insert into tb_test values(5,'Rose');

? 優(yōu)化order by語句

1、環(huán)境準(zhǔn)備

CREATE TABLE `emp` (
?`id` int(11) NOT NULL AUTO_INCREMENT,
?`name` varchar(100) NOT NULL,
?`age` int(3) NOT NULL,
?`salary` int(11) DEFAULT NULL,
?PRIMARY KEY (`id`)
);

insert into `emp` (`id`, `name`, `age`, `salary`) values('1','Tom','25','2300');
insert into `emp` (`id`, `name`, `age`, `salary`) values('2','Jerry','30','3500');
insert into `emp` (`id`, `name`, `age`, `salary`) values('3','Luci','25','2800');
insert into `emp` (`id`, `name`, `age`, `salary`) values('4','Jay','36','3500');
insert into `emp` (`id`, `name`, `age`, `salary`) values('5','Tom2','21','2200');
insert into `emp` (`id`, `name`, `age`, `salary`) values('6','Jerry2','31','3300');
insert into `emp` (`id`, `name`, `age`, `salary`) values('7','Luci2','26','2700');
insert into `emp` (`id`, `name`, `age`, `salary`) values('8','Jay2','33','3500');
insert into `emp` (`id`, `name`, `age`, `salary`) values('9','Tom3','23','2400');
insert into `emp` (`id`, `name`, `age`, `salary`) values('10','Jerry3','32','3100');
insert into `emp` (`id`, `name`, `age`, `salary`) values('11','Luci3','26','2900');
insert into `emp` (`id`, `name`, `age`, `salary`) values('12','Jay3','37','4500');

create index idx_emp_age_salary on emp(age,salary);

2、兩種排序方式

第一種是通過對(duì)返回?cái)?shù)據(jù)進(jìn)行排序,也就是通常說的 filesort 排序,所有不是通過索引直接返回排序結(jié)果的排序都叫 FileSort 排序。

第二種通過有序索引順序掃描直接返回有序數(shù)據(jù),這種情況即為 using index,不需要額外排序,操作效率高。

3、Filesort 的優(yōu)化

通過創(chuàng)建合適的索引,能夠減少 Filesort 的出現(xiàn),但是在某些情況下,條件限制不能讓Filesort消失,那就需要加快 Filesort的排序操作。對(duì)于Filesort , MySQL 有兩種排序算法:

1) 兩次掃描算法 :MySQL4.1 之前,使用該方式排序。首先根據(jù)條件取出排序字段和行指針信息,然后在排序區(qū) sort buffer 中排序,如果sort buffer不夠,則在臨時(shí)表 temporary table 中存儲(chǔ)排序結(jié)果。完成排序之后,再根據(jù)行指針回表讀取記錄,該操作可能會(huì)導(dǎo)致大量隨機(jī)I/O操作。

2)一次掃描算法:一次性取出滿足條件的所有字段,然后在排序區(qū) sort buffer 中排序后直接輸出結(jié)果集。排序時(shí)內(nèi)存開銷較大,但是排序效率比兩次掃描算法要高。

MySQL 通過比較系統(tǒng)變量 max_length_for_sort_data 的大小和Query語句取出的字段總大小, 來判定是否那種排序算法,如果max_length_for_sort_data 更大,那么使用第二種優(yōu)化之后的算法;否則使用第一種。

可以適當(dāng)提高 sort_buffer_size 和 max_length_for_sort_data 系統(tǒng)變量,來增大排序區(qū)的大小,提高排序的效率。

? 優(yōu)化group by

于GROUP BY 實(shí)際上也同樣會(huì)進(jìn)行排序操作,而且與ORDER BY 相比,GROUP BY 主要只是多了排序之后的分組操作。當(dāng)然,如果在分組的時(shí)候還使用了其他的一些聚合函數(shù),那么還需要一些聚合函數(shù)的計(jì)算。所以,在GROUP BY 的實(shí)現(xiàn)過程中,與 ORDER BY 一樣也可以利用到索引。

如果查詢包含 group by 但是用戶想要避免排序結(jié)果的消耗, 則可以執(zhí)行order by null 禁止排序。如下 :

drop index idx_emp_age_salary on emp;

explain select age,count(*) from emp group by age;

explain select age,count(*) from emp group by age order by null;

create index idx_emp_age_salary on emp(age,salary);

? 優(yōu)化子查詢

使用子查詢可以一次性的完成很多邏輯上需要多個(gè)步驟才能完成的SQL操作,同時(shí)也可以避免事務(wù)或者表鎖死,并且寫起來也很容易。但是,有些情況下,子查詢是可以被更高效的連接(JOIN)替代。

explain select * from user where uid in (select uid from user_role );


explain select * from user u , user_role ur where u.uid = ur.uid;


system>const>eq_ref>ref>range>index>ALL

連接(Join)查詢之所以更有效率一些 ,是因?yàn)镸ySQL不需要在內(nèi)存中創(chuàng)建臨時(shí)表來完成這個(gè)邏輯上需要兩個(gè)步驟的查詢工作。

? 優(yōu)化limit查詢

一般分頁(yè)查詢時(shí),通過創(chuàng)建覆蓋索引能夠比較好地提高性能。一個(gè)常見又非常頭疼的問題就是 limit 900000,10 ,此時(shí)需要MySQL排序前900010 記錄,僅僅返回900000 - 900010 的記錄,其他記錄丟棄,查詢排序的代價(jià)非常大 。

1、優(yōu)化思路一

在索引上完成排序分頁(yè)操作,最后根據(jù)主鍵關(guān)聯(lián)回原表查詢所需要的其他列內(nèi)容。

2、優(yōu)化思路二

該方案適用于主鍵自增的表,可以把Limit 查詢轉(zhuǎn)換成某個(gè)位置的查詢 。


必須掌握的MySQL優(yōu)化方式!的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
孝义市| 杂多县| 大安市| 八宿县| 满洲里市| 堆龙德庆县| 中江县| 宾川县| 永城市| 平定县| 自贡市| 南陵县| 株洲县| 竹山县| 河东区| 安仁县| 昌宁县| 涿州市| 叶城县| 连平县| 南宫市| 偏关县| 和田县| 神池县| 哈密市| 临洮县| 乾安县| 丹寨县| 永嘉县| 罗江县| 玛多县| 荔浦县| 新营市| 多伦县| 绿春县| 法库县| 福鼎市| 盐边县| 富顺县| 珠海市| 乌拉特后旗|