MySQL学習の高度な2クエリインターセプト分析

クエリ傍受分析

1.クエリの最適化

1.小さなテーブルが大きなテーブルを動かす

1.mysqlの最適化分析手順

(1)観察し、少なくとも1日実行して、SQLの生成が遅いことを確認します。

(2)遅いクエリログを開き、しきい値を設定します。たとえば、5秒を超える場合は、遅いSQLであり、それを取得します。

(3)explain +遅いSQL分析

(4)プロフィールを表示

(5)運用保守管理者またはDBA、SQLデータベースサーバーのパラメータ調整を行う

総括する

(1)クエリの最適化

(2)遅いクエリを開始してキャプチャする

(3)explain +遅いSQL分析

(4)show profileは、MysqlサーバーでのSQLの実行の詳細とライフサイクルを照会します。

(5)SQLデータベースサーバーのパラメータ調整。

2、INまたはEXISTS

(1)最適化の原則:次のネストされたループのように、小さなテーブルは大きなテーブルを駆動します。つまり、小さなデータセットは大きなデータセットを駆動します。

// 只需要连接5次,每一次都可以执行1000次。小嵌套驱动大语句
for(int i = 5;....){
    
    
	for(int i = 1000;....){
    
    
		....
	}
}

//需要连接的次数为1000次,浪费时间
for(int i = 1000;....){
    
    
	for(int i = 5;....){
    
    
		....
	}
}

(2)IN

テーブルBのデータセットをテーブルAのデータセットよりも小さくする必要がある場合は、inを使用する方が既存よりも優れています。

select * from A where id in(select id from B);
-- 等价于下面的语句
for select id from B  -- 小表
for select * from A where A.id = B.id -- 大表

(3)存在

テーブルAのデータセットをテーブルBのデータセットよりも小さくする必要がある場合は、existsを使用する方がinよりも優れています。

-- select 1(常量就可以,可以为3或者'x'等)。select 1可以换成任意东西,mysql会自动忽略select后面的内容。
select * from A where exists(select 1 from B where A.id = B.id);
-- 等价于下面的语句
for select * from A
for select * from B where A.id = B.id

存在する分析は次のとおりです。

select _ from table where exists(subquery);

メインクエリのデータをサブクエリに入れて条件付き検証を行い、検証結果に応じてメインクエリのデータ結果を保持できるかどうかを判断します。

画像-20200829202119559

2.キーワードの最適化による順序付け

画像-20200829202320394

1.テーブルSQLを作成します

create table tb1A(
age int,
birth timestamp not null
);

-- 插入数据
insert into tb1A(age,birth) values(22,now());
insert into tb1A(age,birth) values(23,now());
insert into tb1A(age,birth) values(24,now());

-- 创建索引
create index idx_A_ageBirth on tb1A(age,birth);

2.最適化

1.次のステートメントを実行します

(1)インデックスを使用し、出力が正常な場合

EXPLAIN SELECT * FROM tb1A WHERE age>20 ORDER BY age;
EXPLAIN SELECT * FROM tb1A WHERE age>20 ORDER BY age,birth;
画像-20200829203305696

(2)インデックスは使用されますが、ファイルソートが発生します

EXPLAIN SELECT * FROM tb1A WHERE age>20 ORDER BY birth;
EXPLAIN SELECT * FROM tb1A WHERE age>20 ORDER BY birth,age;
画像-20200829203431800

(3)SQLは2つの方法でスキャンをサポートします

FileSortとIndexは、Indexの方が効率的ですが、MySQLがインデックス自体をスキャンして並べ替えを完了することを意味します。FileSortメソッドは効率が低くなります。Order byは、次の2つの条件を満たすため、インデックスの並べ替えをサポートします。

order by 语句使用索引最左前列
使用where子句与order by子句条件列组合满足索引最左前列

2.シングル/デュアルウェイソーティング

(1)一方向の並べ替え

一方向ソート(mysql4.1以降)は、クエリに必要なすべての列をディスクから読み取り、列の順序に従ってバッファー内でソートしてから、ソートされたリストをスキャンして出力します。より効率的で、最初にデータをもう一度読み取ります。また、ランダムIOをシーケンシャルIOに変換しますが、各行をメモリに保存するため、より多くのスペースを使用します。

シングルチャネルは後方にあるため、一般的にデュアルチャネルよりも優れており、問題は次のとおりです。

画像-20200829204131189

最適化戦略:

增大sort_buffer_size参数设置
增大max_length_for_sort_data参数设置

(2)双方向ソート

画像-20200829204003218

3.注文の速度を向上させる

(1)select *による順序付けがタブーであり、クエリに必要なフィールドのみである場合、これは非常に重要です。ここでの影響は次のとおりです。

(A)クエリのフィールドサイズの合計がmaxlength-for-sort-data未満で、並べ替えフィールドがTEXTIBLOBタイプでない場合、改善されたアルゴリズム-1つの単一の方法で並べ替えが使用されます。それ以外の場合は古いアルゴリズムが使用されます。 -複数の方法で並べ替えが使用されます。

(B)2つのアルゴリズムのデータがソートバッファの容量を超える可能性があります。その後、マージソート用にtmpファイルが作成され、複数のI / Oが発生しますが、単一チャネルのソートアルゴリズムを使用するリスクが高くなります。 、したがって、sort-buffer-sizeを増やします。

(2)ソートバッファサイズを大きくしてみてください。どのアルゴリズムを使用する場合でも、このパラメータを大きくすると効率が向上します。もちろん、このパラメータは各プロセスに固有であるため、システムの能力に応じて改善する必要があります。

(3)ソートデータの最大長を増やしてみてください|このパラメーターを増やすと、改善されたアルゴリズムを使用する可能性が高くなります。ただし、設定が高すぎると、合計データ容量がソートバッファサイズを超える可能性が高くなります。明らかな症状は、ディスク1 / Oアクティビティが高く、プロセッサの使用率が低いことです。

4.小さな要約

画像-20200829204525863

3.キーワードの最適化によるグループ化

による注文に似ています。

画像-20200829204601369

2.遅いクエリログ

1はじめに

1。概要

MySQLの低速クエリログは、MySQLが提供するログレコードであり、応答時間がMySQLのしきい値を超えるステートメントを記録するために使用されます。具体的long_query_timeには、実行時間が値を超えるSQLが低速クエリログに記録されます。

具体的long_query_timeには、実行時間が値を超えるSQLは、低速クエリログに記録されます。long_query_timeデフォルト値は10です。これは、10秒より長いステートメントを実行することを意味します。

どのSQLが最大耐久時間の値を超えているかを確認するのは彼の責任です。たとえば、SQLが5秒を超えて実行される場合、SQLが遅い場合でも、5秒を超えるSQLを収集して実行したいと考えています。前の説明と組み合わせた包括的な分析。

2.説明

デフォルトでは、MySQLデータベースは低速クエリログを有効にしないため、このパラメータを手動で設定する必要があります。

もちろん、チューニングに必要ない場合は、このパラメーターを有効にすることは通常お勧めしません。遅いクエリログをオンにすると、パフォーマンスにある程度の影響が生じるためです。遅いクエリログは、ファイルへのログレコードの書き込みをサポートします。

2.操作

1.開店状況を確認する

show VARIABLES LIKE '%slow_query_log%';

-- 开启。开启慢查询日志只对当前数据库生效,如果MySQL重启后则会失
效。
set global slow_query_log=1;
画像-20200829205250189

通常、低速クエリログを永続的に有効にすることはお勧めしません。これを行う必要がある場合は、構成ファイルmy.cnfのみを変更できます。

画像-20200829205400637

2.遅い時間のしきい値を確認します

show VARIABLES LIKE '%long_query_time%';

デフォルトのlong_query_timeは10秒です。つまり、10秒を超えるSQLは低速クエリログに記録されます。以下。SQLステートメントの実行時間がlong_query_timeで設定された時間よりも長い場合、ログに記録されます。

テストのために、SQLステートメント実行のしきい値時間を3Sに設定します。

set global long_query_time=3;

この時点で、変数は変更されていlong_query_timeますlong_query_timeが、クエリ内の変数の値は10のままです。

画像-20200829205819044

この時点で、セッションを再度開くか、次のコマンドを使用してクエリを実行する必要があります。

show GLOBAL VARIABLES LIKE '%long_query_time%';

遅いログファイルをクエリすると、次のことがわかります。

画像-20200829211304163

注意:

上記のログについては、次のSQLステートメントを実行する必要があります。

set global long_query_time=3;

現在のFinalShell接続を再切断してから、次のステートメントを実行して確認します。

select sleep(4);

3.永続的に有効になるようにしきい値時間を設定します

-- [mysqld]下配置
slow_query_log=1;
slow_query_log_file=/usr/local/mysql/data/hadoop101-slow.log;
long_query_time=3;
log_output=FILE;

4.ログ分析ツール-mysqldumpslow

実稼働環境では、ログを手動で分析し、SQLを見つけて分析する場合、それは手動のタスクです。MySQLはログ分析ツールmysqldumpslowを提供します。

(1)ヘルプ情報を表示する

mysqldumpslow --help
画像-20200829211937491

(2)パラメータ

画像-20200829211958271

(3)共通コマンド作業の共通リファレンス

画像-20200829212020983

3.バッチデータスクリプト

1はじめに

関数とストアドプロシージャの違い:関数には戻り値がありますが、ストアドプロシージャにはありません。

画像-20200829212117018

2.操作-1000wデータをテーブルに挿入します

画像-20200829212156934

1.テーブルSQLを作成します

-- 新建库
create database bigData;
use bigData;


-- 部门表
create table dept(
id int unsigned primary key auto_increment,
deptno mediumint unsigned not null default 0,
dname varchar(20) not null default "",
loc varchar(13) not null default ""
)engine=innodb default charset=utf8;

-- 员工表
create table emp(
id int unsigned primary key auto_increment, 
empno mediumint unsigned not null default 0, /*编号*/
ename varchar(20) not null default "", /*名字*/
job varchar(9) not null default "",  /*工作*/
mgr mediumint unsigned not null default 0, /*上级编号*/
hiredate date not null, /*入职时间*/
sal decimal(7,2) not null, /*薪水*/
comm decimal(7,2) not null, /*红利*/
deptno  mediumint unsigned not null default 0,/*部门编号*/
)engine=innodb default charset=utf8;

2.パラメータlog_bin_trust_function_creatorsを設定します

画像-20200829213405835
show variables like 'log_bin_trust_function_creators';
set global log_bin_trust_function_creators = 1;
画像-20200829213538501

3.各データが異なることを確認する関数を作成します

(1)文字列をランダムに生成する

-- delimiter 定界符
delimiter $$
 -- ran_string 函数名,返回值类型 varchar(255) 
CREATE FUNCTION `rand_string`(n int) RETURNS varchar(255) 
BEGIN
	-- 定义变量chars_str
  DECLARE chars_str VARCHAR(100) DEFAULT
  'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  -- 声明返回类型
  DECLARE return_str VARCHAR(255) DEFAULT '';
  DECLARE i INT DEFAULT 0;
  WHILE i < n DO
  -- 从 chars_str 中随机取一个字符;CONCAT函数将多个字符串连接成一个字符串。
  SET return_str = CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
  SET i = i + 1;
	END WHILE;
RETURN return_str;
END  $$

(2)部門番号をランダムに生成する

delimiter $$
CREATE FUNCTION `rand_num`() RETURNS int(5)
BEGIN
  DECLARE i INT DEFAULT 0;
  -- 100~ 110之间部门号
  SET i=FLOOR(100+RAND()*10);
RETURN i;
END  $$

-- 加入要删除函数,使用下面命令
drop function rand_num;

4.ストアドプロシージャを作成します

(1)従業員テーブルempにデータを挿入するプロセス

delimiter $$
  CREATE  PROCEDURE `insert_emp`(IN START INT(10),IN max_num INT(10))
  BEGIN
    DECLARE i INT DEFAULT 0;
    -- 关闭每次插入数据后自动提交,节省时间
    SET autocommit = 0;
    REPEAT
    SET i = i + 1;
    INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
    VALUES((START+i),rand_string(6),'SALESMAN',0001,CURDATE(),2000,400,rand_num());
    UNTIL i = max_num
  END REPEAT;
  -- 对于插入的50w条数据,一次性提交
  COMMIT; 
END $$

(1)部門テーブル部門にデータを挿入するプロセス

delimiter $$
  CREATE PROCEDURE `insert_dept`(IN START int,IN max_num int)
  BEGIN
    DECLARE i INT DEFAULT 0;
    SET autocommit = 0;
    REPEAT
    SET i = i + 1;
    INSERT INTO dept(deptno,dname,loc) VALUES((START+i),rand_string(10),rand_string(8));
    UNTIL i = max_num
  END REPEAT;
  COMMIT;
END $$

5.ストアドプロシージャを呼び出します

(1)部門テーブル部門に10の部門データを挿入します

-- 换回分界符
delimiter ;

-- call表示调用函数
CALL insert_dept(100,10);
画像-20200829221540765

(2)500,000個のデータをemployee tableempに挿入します

合計1000wを挿入しましたが、データベースへの負担を軽減するため、20回の完成となりました。

-- 换回分界符
delimiter ;

-- call表示调用函数
-- CALL insert_emp(1,500000);
-- 为了简便起见,插入1000条数据进行测试
CALL insert_emp(1,1000);
画像-20200829222358825

4、プロフィールを表示

1はじめに

画像-20200829222513009

mysqlは、現在のセッションでのステートメント実行のリソース消費を分析するために使用されます。

1.現在のショープロファイルステータスを表示します

-- 默认是关闭的,使用前需要进行开启
show variables like 'profiling';

-- 开启
set profiling=on;
画像-20200829222756609

2.SQLを実行します

select * from emp;
select * from emp limit 10;

3.結果を表示します

show profiles;
画像-20200829223423986
-- 3 对应show profiles;查询中的query_id
show profile cpu,block io for query 3;
画像-20200829223520150

それらの中で、showprofileの後に他のパラメータを続けることができます。

画像-20200829223601779

上記のクエリの結果については、これらの指標に注意を払う必要があります。

  • HEAPをMYISAMに変換する:クエリの結果が大きすぎ、メモリが不足しているため、ディスクに移動し始めました
  • tmpテーブルの作成:一時テーブルを作成します(データを一時テーブルにコピーし、使用後に削除します)
  • ディスク上のtmpテーブルへのコピー(メモリ内の一時テーブルをディスクにコピーすることは非常に危険です!!!)
  • ロックされています
画像-20200829224030561

5.グローバルクエリログ

この機能は実稼働環境では有効にしないでください。主にテスト環境で使用されます。

1.構成して有効にします

my.cnfファイルの設定は次のとおりです。

#开启
general_log=1

#记录日志文件的路径./path/logfile可以设置指定
general_log_file = /path/logfile

#输出格式
log_output=FILE

2.エンコーディングが有効になっている

set global general_log=1;
set global log_output = 'TABLE';

その後、作成したsqlステートメントがmysqlライブラリのgeneral_logテーブルに記録され、次のコマンドを使用して表示できます。

-- mysql是一个系统的数据库
select * from mysql.general_log;
画像-20200829224908016

showprofileを使用することをお勧めします。

おすすめ

転載: blog.csdn.net/weixin_43334389/article/details/113928849