MySQLの最適化(アプリケーション、キャッシュ、メモリ管理、ロック、一般的に使用されるSQLのスキル)

含む(アプリケーションの最適化、クエリキャッシュを最適化し、メモリ管理の最適化、同時パラメータ調整、ロックの問題、SQLのスキル)

アプリケーションの最適化

1接続プールを使用して
、我々は頻繁に近い接続を作成するため、接続のコストの設立は、比較的高価であり、データベースにアクセスするために、それはより多くのリソースを大量に消費され、我々はパフォーマンスのアクセスを改善するために、データベース接続プールを確立する必要があります。
MySQLのアクセス減らすために2
避けるようにデータ検索が繰り返されます。

select id , name from tb_book;
select id , status from tb_book; 
可以一次性查出来
select id, name , status from tb_book; 

キャッシュ層を増やし
、我々は、データベースの負荷を軽減する目的を達成するために、アプリケーション層でキャッシュを増やすことができ、アプリケーションに。バッファ層は、アプリケーションの要件をすることができ会うことができるデータベースを低減させる負担限り、達成することができ、達成するための多くの方法がありますが、多くがあります。アプリケーション側に格納されたテキストにデータベースから抽出されたデータの一部であっても、またはフレーム(MyBatisの、休止状態)を使用して、バッファ/キャッシュを提供し、使用のRedisデータベースまたはキャッシュデータができます。
3ロードバランシング
ロードバランシングは、最適化の方法で使用される非常に一般的なアプリケーションであり、そのメカニズムはバランシングアルゴリズムのいくつかの種類を使用することで、負荷の固定量は、単一のサーバの負荷を軽減するために、異なるサーバ上に分散されるように、達成するために最適な結果を得ます。
使用MySQLのレプリケーションシャント問い合わせ
別々のリードの複製によるマスターからMySQLおよびそれによって圧力測定値を低減し、単一のサーバを書き込み、離れクエリノードから離れマスタノードCRUD操作を書き込みます。
ここに画像を挿入説明
分散データベース・アーキテクチャ
大量のデータ、高負荷条件のためのデータベースアーキテクチャを分散、それは良いスケーラビリティと高可用性を持っています。複数のサーバー間でデータを分散することで、アクセス効率を向上させるために、複数のサーバー間で負荷分散を実現することができます。

MySQLのクエリキャッシュの最適化

オープンMySQLのクエリキャッシュまったく同じSQL文を実行するときに、サーバーは、キャッシュテーブルがクエリキャッシュには適していません修正より頻繁に失敗する前に、データが変更されたとき、その結果、キャッシュから直接読み込みます。
操作手順

1. 客户端发送一条查询给服务器;
2. 服务器先会检查查询缓存,如果命中了缓存,则立即返回存储在缓存中的结果。否则进入下一阶段;
3. 服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划;
4. MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询;
5. 将结果返回给客户端。

ここに画像を挿入説明
クエリキャッシュの設定

查看当前的MySQL数据库是否支持查询缓存:
	SHOW VARIABLES LIKE 'have_query_cache';
查看当前MySQL是否开启了查询缓存 :
	SHOW VARIABLES LIKE 'query_cache_type'; 
查看查询缓存的占用大小 :单位是字节byte
	SHOW VARIABLES LIKE 'query_cache_size'; 
查看查询缓存的状态变量:
	SHOW STATUS LIKE 'Qcache%'; 

ここに画像を挿入説明
ここに画像を挿入説明
次のように変数の意味は以下のとおりです。

参数含义
	Qcache_free_blocks 查询缓存中的可用内存块数
	Qcache_free_memory 查询缓存的可用内存量
	Qcache_hits 查询缓存命中数
	Qcache_inserts 添加到查询缓存的查询数
	Qcache_lowmen_prunes 由于内存不足而从查询缓存中删除的查询数
	Qcache_not_cached 非缓存查询的数量(由于 query_cache_type 设置而无法缓存或未缓存)
	Qcache_queries_in_cache 查询缓存中注册的查询数
	Qcache_total_blocks 查询缓存中的块总数

クエリキャッシュを有効にします
MySQLのクエリキャッシュクエリキャッシュを開くために、手動での設定パラメータquery_cache_typeの必要性は、デフォルトでオフになっています。このパラメータには、三つの値を有することができるquery_cache_type:

值 含义
OFF 或 0 查询缓存功能关闭
ON  或 1 查询缓存功能打开,SELECT的结果符合缓存条件即会缓存,否则,不予缓存,显式指定
SQL_NO_CACHE,不予缓存
DEMAND 或 2 查询缓存功能按需进行,显式指定 SQL_CACHE 的SELECT语句才会缓存;其它均不予缓存

/usr/my.cnf構成では、以下の設定を追加します。
ここに画像を挿入説明
設定が完了したら、サービスを有効にすることができます再起動し、行くかどうかを判断するために、クエリキャッシュ、クエリキャッシュを見て、キャッシュヒットの数を取得します。
クエリキャッシュでのSELECTオプション

可以在SELECT语句中指定两个与查询缓存相关的选项 :
SQL_CACHE : 如果查询结果是可缓存的,并且 query_cache_type 系统变量的值为ON或 DEMAND ,则缓存查询
结果 。
SQL_NO_CACHE : 服务器不使用查询缓存。它既不检查查询缓存,也不检查结果是否已缓存,也不缓存查询结果。
例子:
SELECT SQL_CACHE id, name FROM customer;
SELECT SQL_NO_CACHE id, name FROM customer;

キャッシュ無効化のステータスを確認

1、SQL 语句不一致的情况, 要想命中查询缓存,查询的SQL语句必须一致。
如下:s大小写不同也不行
	SQL1 : select count(*) from tb_item;
	SQL2 : Select count(*) from tb_item;
2、当查询语句中有一些不确定的时,则不会缓存。如 : now() , current_date() , curdate() , curtime() , rand() ,
uuid() , user() , database() 。
	如:select * from tb_item where updatetime < now() limit 1;
3、不使用任何表查询语句。
	select 'A'; 
4、查询 mysql, information_schema或 performance_schema 数据库中的表时,不会走查询缓存。
	select * from information_schema.engines; 
5、在存储的函数,触发器或事件的主体内执行的查询。
6、 如果表更改,则使用该表的所有高速缓存查询都将变为无效并从高速缓存中删除。这包括使用 MERGE 映射到
已更改表的表的查询。一个表可以被许多类型的语句,如被改变 INSERT, UPDATE, DELETE, TRUNCATE
TABLE, ALTER TABLE, DROP TABLE,或 DROP DATABASE 。

MySQLのメモリ管理と最適化

メモリの最適化の原則

1) 将尽量多的内存分配给MySQL做缓存,但要给操作系统和其他程序预留足够内存。
2) MyISAM 存储引擎的数据文件读取依赖于操作系统自身的IO缓存,因此,如果有MyISAM表,就要预留更多的
内存给操作系统做IO缓存。
3) 排序区、连接区等缓存是分配给每个数据库会话(session)专用的,其默认值的设置要根据最大连接数合理
分配,如果设置太大,不但浪费资源,而且在并发连接较高时会导致物理内存耗尽

MyISAMのメモリの最適化

myisam存储引擎使用 key_buffer 缓存索引块,加速myisam索引的读写速度。对于myisam表的数据块,mysql没
有特别的缓存机制,完全依赖于操作系统的IO缓存。

key_buffer_sizeは

key_buffer_size决定MyISAM索引块缓存区的大小,直接影响到MyISAM表的存取效率。可以在MySQL参数文件中
设置key_buffer_size的值,对于一般MyISAM数据库,建议至少将1/4可用内存分配给key_buffer_size
在/usr/my.cnf 中做如下配置:
	key_buffer_size=512M 

read_buffer_size

如果需要经常顺序扫描myisam表,可以通过增大read_buffer_size的值来改善性能。但需要注意的是
read_buffer_size是每个session独占的,如果默认值设置太大,就会造成内存浪费。

read_rnd_buffer_size

对于需要做排序的myisam表的查询,如带有order by子句的sql,适当增加 read_rnd_buffer_size 的值,可以改善
此类的sql性能。但需要注意的是 read_rnd_buffer_size 是每个session独占的,如果默认值设置太大,就会造成内
存浪费。

InnoDBのメモリの最適化
nnodb専用キャッシュ・プールのInnoDBキャッシュブロックだけでなく、キャッシュのInnoDBのデータブロックのインデックスに使用されていないメモリ領域とIOバッファプールを行います。
innodb_buffer_pool_size

该变量决定了 innodb 存储引擎表数据和索引数据的最大缓存区大小。在保证操作系统及其他程序有足够内存可用
的情况下,innodb_buffer_pool_size 的值越大,缓存命中率越高,访问InnoDB表需要的磁盘I/O 就越少,性能也
就越高。
	innodb_buffer_pool_size=512M 

innodb_log_buffer_size

决定了innodb重做日志缓存的大小,对于可能产生大量更新记录的大事务,增加innodb_log_buffer_size的大小,
可以避免innodb在事务提交前就执行不必要的日志写入磁盘操作。
	innodb_log_buffer_size=10M 

MySQLの同時実行パラメータの調整

从实现上来说,MySQL Server 是多线程结构,包括后台线程和客户服务线程。多线程可以有效利用服务器资源,
提高数据库的并发性能。在Mysql中,控制并发连接和线程的主要参数包括 max_connections、back_log、
thread_cache_size、table_open_cahce。

MAX_CONNECTIONS

采用max_connections 控制允许连接到MySQL数据库的最大数量,默认值是 151。如果状态变量
connection_errors_max_connections 不为零,并且一直增长,则说明不断有连接请求因数据库连接数已达到允
许最大值而失败,这是可以考虑增大max_connections 的值。
Mysql 最大可支持的连接数,取决于很多因素,包括给定操作系统平台的线程库的质量、内存大小、每个连接的负
荷、CPU的处理速度,期望的响应时间等。在Linux 平台下,性能好的服务器,支持 500-1000 个连接不是难事,
需要根据服务器性能进行评估设定。

やり残し

back_log 参数控制MySQL监听TCP端口时设置的积压请求栈大小。如果MySql的连接数达到max_connections时,
新来的请求将会被存在堆栈中,以等待某一连接释放资源,该堆栈的数量即back_log,如果等待连接的数量超过
back_log,将不被授予连接资源,将会报错。5.6.6 版本之前默认值为 50 , 之后的版本默认为 50 +
(max_connections / 5), 但最大不超过900。
如果需要数据库在较短的时间内处理大量连接请求, 可以考虑适当增大back_log 的值。

table_open_cacheの

该参数用来控制所有SQL语句执行线程可打开表缓存的数量, 而在执行SQL语句时,每一个SQL执行线程至少要打
开 1 个表缓存。该参数的值应该根据设置的最大连接数 max_connections 以及每个连接执行关联查询中涉及的表
的最大数量来设定 :
	max_connections x N ;

thread_cache_size

为了加快连接数据库的速度,MySQL 会缓存一定数量的客户服务线程以备重用,通过参数 thread_cache_size 可
控制 MySQL 缓存客户服务线程的数量。

innodb_lock_wait_timeout

该参数是用来设置InnoDB 事务等待行锁的时间,默认值是50ms , 可以根据需要进行动态设置。对于需要快速反
馈的业务系统来说,可以将行锁的等待时间调小,以避免事务长时间挂起; 对于后台运行的批量处理程序来说,
可以将行锁的等待时间调大, 以避免发生大的回滚操作。

MySQLのロックの問題

锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。在数据库中,除传统的计算资源(如 CPU、RAM、I/O 等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。

ロックカテゴリ

从对数据操作的粒度分 :
1) 表锁:操作时,会锁定整个表。
2) 行锁:操作时,会锁定当前操作行。
从对数据操作的类型分:
1) 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。
2) 写锁(排它锁):当前操作没有完成之前,它会阻断其他写锁和读锁。

各ストレージエンジン支持体は、ケースのロック:
ここに画像を挿入説明
MySQLは、以下のように、これらの三つの特徴を大まかに要約することができるロック。
ここに画像を挿入説明

仅从锁的角度来说:
	表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web 应用;
	行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并查询的应用,如一些在线事务处理(OLTP)系统。

テーブルロックを追加する方法

MyISAM 在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、
INSERT 等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用 LOCK
TABLE 命令给 MyISAM 表显式加锁。
显示加表锁语法:
	加读锁 : lock table table_name read;
    加写锁 : lock table table_name write;
例如读锁案例:
	 1、客户端A获得表的读锁,可以正常执行查询该表 
	    客户端B也可以正常执行查询该表 
	 2、客户端A查询未锁定的表,提示已经锁定一张表了,不能去查询别的未锁定的表。
	    客户端B却可以正常执行查询该表 
	 3、客户端A执行插入操作向锁定的表,直接报错 , 由于当前tb_book 获得的是读锁, 不能执行更新操作。
	    客户端B执行插入操作,等待中。。。当在客户端A中释放锁指令 unlock tables 后 , 客户端B中的 inesrt 语句 , 立即执行 ;
例如写锁案例:
	 1、客户端A获得表的写锁lock table tb_book write ; 执行查询操作成功。执行更新操作成功。
	    客户端B执行查询操作等待中。。。当在客户端A中释放锁指令 unlock tables 后 , 客户端B中的 select 语句 , 立即执行 ;

結論
表に示すように、相互互換性ロックモード:
ここに画像を挿入説明

由上表可见:
1) 对MyISAM 表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;
2) 对MyISAM 表的写操作,则会阻塞其他用户对同一表的读和写操作;
简而言之,就是读锁会阻塞写,但是不会阻塞读。而写锁,则既会阻塞读,又会阻塞写。此外,MyISAM 的读写锁调度是写优先,这也是MyISAM不适合做写为主的表的存储引擎的原因。因为写锁后,其
他线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永远阻塞。

ショーのオープンテーブルを見るロック競合。
ここに画像を挿入説明

In_user : 表当前被查询使用的次数。如果该数为零,则表是打开的,但是当前没有被使用。
Name_locked:表名称是否被锁定。名称锁定用于取消表或对表进行重命名等操作。

「Table_locksの%」のような状態を表示。
ここに画像を挿入説明

Table_locks_immediate : 指的是能够立即获得表级锁的次数,每立即获取锁,值加1。
Table_locks_waited : 指的是不能立即获取表级锁而需要等待的次数,每等待一次,该值加1,此值高说明存在着
较为严重的表级锁争用情况。

InnoDBの行ロック

行锁特点 :偏向InnoDB 存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
InnoDB 与 MyISAM 的最大不同有两点:一是支持事务;二是 采用了行级锁。

InnoDBの行ロックモード

InnoDB 实现了以下两种类型的行锁。
	共享锁(S):又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数
据,但是只能读不能修改。
	排他锁(X):又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他
锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行
读取和修改。
对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);
对于普通SELECT语句,InnoDB不会加任何锁;
可以通过以下语句显示给记录集加共享锁或排他锁 。
共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
排他锁(X) :SELECT * FROM table_name WHERE ... FOR UPDATE
例如:session1、session2分别关闭自动提交功能set autocommit=0;
	 session1-2可以正常的查询出全部的数据
	 session1更新id为3的数据,但是不提交成功
	 session2更新id为3的数据,处于等待状态
	 session1通过commit, 提交事务,session2解除阻塞,更新正常进行
操作不同行的数据
	 session1更新id为3数据,正常的获取到行锁 , 执行更新
	 session2更新id为5的数据,由于与Session-1 操作不是同一行,获取当前行锁,执
行更新;

表ロックするインデックス行ロックのエスカレーションありません
あなたは、インデックス条件を介してデータを取得していない場合は、すべてのレコードは、InnoDBのテーブルロックは、同じ実用的な効果を持つテーブルをロックします。
ここに画像を挿入説明
アップデートを行う際に、名前フィールドはVARCHARを入力しなければならないので、我々は、配列型、型変換の有無、障害の指標として使用し、最終的なテーブルロック行がロックされ、
ロック害ギャップ

当我们用范围条件,而不是使用相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据进
行加锁; 对于键值在条件范围内但并不存在的记录,叫做 "间隙(GAP)" , InnoDB也会对这个 "间隙" 加锁,这
种锁机制就是所谓的 间隙锁(Next-Key锁) 。

ここに画像を挿入説明
InnoDBの行ロック競合
「innodb_row_lockの%」のような状態を表示。
ここに画像を挿入説明

Innodb_row_lock_current_waits: 当前正在等待锁定的数量
Innodb_row_lock_time: 从系统启动到现在锁定总时间长度
Innodb_row_lock_time_avg:每次等待所花平均时长
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花的时间
Innodb_row_lock_waits: 系统启动后到现在总共等待的次数
当等待的次数很高,而且每次等待的时长也不小的时候,我们就需要分析系统中为什么会有如此多的等待,然后根
据分析结果着手制定优化计划。

概要

InnoDB存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面带来了性能损耗可能比表锁会更高一些,但是
在整体并发处理能力方面要远远由于MyISAM的表锁的。当系统并发量较高的时候,InnoDB的整体性能和MyISAM
相比就会有比较明显的优势。
但是,InnoDB的行级锁同样也有其脆弱的一面,当我们使用不当的时候,可能会让InnoDB的整体性能表现不仅不
能比MyISAM高,甚至可能会更差。
优化建议:
	尽可能让所有数据检索都能通过索引来完成,避免无索引行锁升级为表锁。
	合理设计索引,尽量缩小锁的范围
	尽可能减少索引条件,及索引范围,避免间隙锁
	尽量控制事务大小,减少锁定资源量和时间长度
	尽可使用低级别事务隔离(但是需要业务层面满足需求)

一般的なSQLのスキル

SQLの実行順序

编写顺序
SELECT DISTINCT
<select list>
FROM
<left_table> <join_type>
JOIN
<right_table> ON <join_condition>
WHERE
<where_condition>
GROUP BY
<group_by_list>
HAVING
<having_condition>
ORDER BY
<order_by_condition>
LIMIT
<limit_params>
执行顺序
FROM <left_table>
ON <join_condition>
<join_type> JOIN <right_table>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
SELECT DISTINCT <select list>
ORDER BY <order_by_condition>
LIMIT <limit_params>

正規表現を使用します
ここに画像を挿入説明

select * from emp where name regexp '^T';
select * from emp where name regexp '2$';
select * from emp where name regexp '[uvw]';

MySQLの共通機能
数値関数
ここに画像を挿入説明
文字列関数の
ここに画像を挿入説明
日付関数は、
ここに画像を挿入説明
ここに画像を挿入説明
機能を集約します
ここに画像を挿入説明

公開された81元の記事 ウォンの賞賛5 ビュー20000 +

おすすめ

転載: blog.csdn.net/qq_36205206/article/details/103782091