MyISAM と InnoDB
パフォーマンスの低下と SQL の速度低下の理由:
MySQL 実行順序
SQL結合テーブル mysql> tbl_dept から * を選択します。 +----+----------+--------+ | id | 部門名 | 場所追加 | +----+----------+--------+ | 1 | ラウンド | 11 | | 2 | HR | 12 | | 3 | MK | 13 | | 4 | MIS | 14 | | 5 | FD | 15 | +----+----------+--------+ セット内の行数は 5 です (0.00 秒) b テーブル +----+------+--------+ | ID | 名前 | 部門 ID | +----+------+--------+ | 1 | z3 | 1 | | 2 | z4 | 1 | | 3 | z5 | 1 | | 4 | w5 | 2 | | 5 | w6 | 2 | | 6 | s7 | 3 | | 7 | s8 | 4 | | 8 | s9 | 51 | +----+------+--------+ セット内の行数は 8 です (0.00 秒)
mysql> tbl_dept a から * を選択し、 tbl_emp b を a.id=b.deptId で右結合します。 -> 結合 -> tbl_dept a から * を選択し、tbl_emp b を a.id=b.deptId で左結合します。 +------+----------+--------+-------+-------+-------+ | id | deptName | locAdd | id | 名前 | deptId | +------+----------+--------+-------+-------+-------+ | 1 | RD | 11 | 1 | z3 | 1 | | 1 | RD | 11 | 2 | z4 | 1 | | 1 | RD | 11 | 3 | z5 | 1 | | 2 | HR | 12 | 4 | w5 | 2 | | 2 | HR | 12 | 5 | w6 | 2 | | 3 | MK | 13 | 6 | s7 | 3 | | 4 | MIS | 14 | 7 | s8 | 4 | | NULL | NULL | NULL | 8 | s9 | 51 | | 5 | FD | 15 | NULL | NULL | NULL | +------+----------+--------+-------+-------+-------+ セット内の行数は 9 です (0.00 秒) aの一意性とbの一意性
索引インデックスの定義: インデックスは、SQLがデータを効率的に取得するのに役立つデータ構造です。インデックスの本質は、 簡単に言えば、 データベース システムでは、データに加えて、特定の検索アルゴリズムを満たすデータ構造も保持されます。これらのデータ構造は、何らかの方法 (参照) でデータを指し示すため、これらのデータ構造に高度な検索アルゴリズムを実装できます。このデータ構造はインデックスです。次の図は例です。 一般的に、インデックスも非常に大きいため、インデックス ファイルとしてディスクに保存されることがよくあります。 インデックスについて話すときは、特に指定がない限り、通常は B ツリー (多方向検索ツリー、必ずしもバイナリではない) 構造で編成されたインデックスを指します。 このうち、クラスター化インデックス、セカンダリインデックス、複合インデックス、プレフィックスインデックス、ユニークインデックスはすべてデフォルトで B+ ツリーインデックスを使用しており、総称してインデックスと呼ばれます。もちろん、B+ ツリーインデックスの他にハッシュインデックスもあります。 インデックスの長所と短所1. 利点大学図書館の図書番号の索引付けと同様に、データ検索の効率が向上し、データベースの IO コストが削減されます。 インデックスでデータをソートすると、データのソートコストが削減され、CPU消費が削減されます。 2. デメリット実際、インデックスは主キーとインデックス付きのフィールドを格納し、エンティティ テーブルのレコードを指すテーブルでもあるため、インデックス列もスペースを占有します。 インデックスはクエリ速度を大幅に向上させますが、更新、挿入、削除などのテーブル更新操作は遅くなります。これは、テーブルを更新するときに、MySQL はデータだけでなくインデックス ファイルも保存する必要があるためです。インデックスを使用してフィールドを更新するたびに、更新によってキー値が変更された後にインデックス情報が調整されます。 インデックスは効率を向上させるための 1 つの要素にすぎません。大量のデータを含むテーブルの場合、効率を向上させるために単にインデックスを追加するのではなく、最適なインデックスを作成するか、優れたクエリ ステートメントを記述する必要があります。 インデックス分類
作成するmytable(cloumnname(length)) に [一意の] インデックス indexName を作成します。 alter mytable に [unique] index [indexName] を (columnname(length)) に追加します。 消去mytableのインデックス[indexName]を削除します チェックtable_name\G からインデックスを表示 テーブルにインデックスを追加する方法は 4 つあります。 MySQL インデックス構造
どのような場合にインデックスを作成する必要がありますか?
インデックスを作成しない方が良い場合
パフォーマンス分析要点を説明する 何ができるでしょうか?
イドの3つの状況
選択タイプ
タイプ::タイプはアクセスタイプの配置を示し、これはより重要な指標である 最高から最低の順に次のとおりです。 一般的に言えば、クエリが少なくとも範囲レベル、できればrefレベルに到達することを確認する必要があります。
key_lenの長さ: 13 char(4)*utf8(3)+nullが許可される(1)=13
インデックスが作成されていない場合は、t1 t2 テーブルをクエリします。t2 テーブルに対応する t1 テーブルの ID。t2 テーブルの col1 の値は 'ac' である必要があります。 Id フィールドの場合、テーブル t1 はテーブル t2 の 1 対多に相当します。 t1 テーブルのタイプは eq_ref で、これはユニーク インデックス スキャンを意味します。テーブル内にはそれに一致するレコードが 1 つだけあります。t2 テーブルには、t1 テーブルの id に対応する col 値が 1 つだけあります。t2 テーブルの主キー id インデックス クエリによると、t1 テーブルから 1 行が読み取られ、t2 テーブルから 640 行が読み取られます。 インデックス作成後 t1 は 1 行を読み取り、t2 は 142 行を読み取り、ref は非一意インデックス スキャンを実行し、単一の値に一致するすべての行を返し、t2 の id に対応する列のすべての行を返しますが、t1 には id に対応する列の行が 1 つしかないため、型は eq_ref です。 余分な他の列に収まらない重要な情報が含まれています \G : 縦に並び替えて表示
場合 インデックスの最適化単一テーブルの最適化存在しない場合はテーブルを作成します `article`( `id` INT(10) UNSIGNED NOT NULL 主キー AUTO_INCREMENT, `author_id` INT (10) UNSIGNED NOT NULL, `category_id` INT(10) UNSIGNED NOT NULL , `views` INT(10) UNSIGNED NOT NULL , `コメント` INT(10) UNSIGNED NOT NULL, `title` VARBINARY(255) NOT NULL、 `content` テキストが NULL ではありません ); `article`(`author_id`,`category_id`,`views`,`comments`,`title`,`content`) に値を挿入します (1,1,1,1,'1','1')、 (2,2,2,2,'2','2')、 (1,1,3,3,'3','3'); 記事から*を選択; mysql> category_id = 1 かつ comments > 1 の場合、記事から id、author_id を選択し、views desc limit 1 で並べ替えます。 +----+-----------+ | id | 著者ID | +----+-----------+ | 3 | 1 | +----+-----------+ セット内の 1 行 (0.00 秒) mysql> explain select author_id from article where category_id = 1 and comments > 1 order by views desc li 1を模倣する; +----+-------------+----------+-----------+--------+-------+-------+--------+---------+-----------------------------+-----+-------+---------+----------+-----------------------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+----------+-----------+--------+-------+-------+--------+---------+-----------------------------+-----+-------+---------+----------+-----------------------------+ | 1 | SIMPLE | article | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | where の使用; filesort の使用 | +----+-------------+----------+-----------+--------+-------+-------+--------+---------+-----------------------------+-----+-------+---------+----------+-----------------------------+ セットに 1 行、警告 1 件 (0.00 秒) クエリは完了しているものの、type が all であり、Extra に using filesort が表示されており、クエリ効率が非常に低いことがわかります。 最適化が必要 インデックスを作成する article(category_id,comments,views) にインデックス idx_article_ccv を作成します。 クエリ mysql> explain select author_id from article where category_id = 1 and comments > 1 order by views desc limit 1; +----+-------------+----------+-----------+--------+-------+-------+--------+---------------------------------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+----------+-----------+--------+-------+-------+--------+---------------------------------------+ | 1 | SIMPLE | article | NULL | range | inx_article_ccv | inx_article_ccv | 8 | NULL | 1 | 100.00 | インデックス条件を使用; filesort を使用 | +----+-------------+----------+-----------+--------+-------+-------+--------+---------------------------------------+ セットに 1 行、警告 1 件 (0.00 秒) ここで、型が範囲に変更され、テーブル全体のクエリが範囲クエリに変更され、少し最適化されていることがわかります。 ただし、extra は依然として filesort を使用しているため、インデックスの最適化が成功していないことがわかります。 そこでインデックスを削除します 記事のインデックス idx_article_ccv を削除します。 新しいインデックスを作成し、範囲を除外する article(category_id,views) にインデックス idx_article_cv を作成します。 mysql> explain select author_id from article where category_id = 1 and comments > 1 order by views desc limit 1; +----+-------------+----------+-----------+--------+----------------+----------------+----------+---------+-----------+-------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+----------+-----------+--------+----------------+----------------+----------+--------+-----------+-------------+ | 1 | SIMPLE | article | NULL | ref | idx_article_cv | idx_article_cv | 4 | const | 2 | 33.33 | where の使用 | +----+-------------+----------+-----------+--------+----------------+----------------+----------+--------+-----------+-------------+ セットに 1 行、警告 1 件 (0.00 秒) この時点で最適化が成功していることがわかります。型はrefに変更され、extraはusing whereに変更されました。 この実験では、別のテストを追加して、インデックスを作成するときに最後にコメントを配置することも可能であることがわかりました。mysql> create index idx_article_cvc on article(category_id,views,comments); クエリは正常、影響を受けた行は 0 行 (0.02 秒) レコード: 0 重複: 0 警告: 0 mysql> explain select author_id from article where category_id = 1 and comments > 1 order by views desc limit 1; +----+-------------+----------+-----------+--------+-----------------+---------+---------+-----------+-------------+-------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+----------+-----------+--------+-----------------+---------+---------+-----------+-------------+-------------+ | 1 | SIMPLE | article | NULL | ref | idx_article_cvc | idx_article_cvc | 4 | const | 2 | 33.33 | where の使用 | +----+-------------+----------+-----------+--------+-----------------+---------+---------+-----------+-------------+-------------+ セットに 1 行、警告 1 件 (0.00 秒)
ここで、type はまだ ref であり、extra はまだ usingwhere であることがわかりますが、インデックス作成位置が変更され、範囲クエリ フィールドが最後に移動されています。 デュアルテーブル最適化`class`が存在しない場合はテーブルを作成します( `id` INT(10) UNSIGNED NOT NULL 主キー AUTO_INCREMENT, `カード` INT (10) UNSIGNED NOT NULL ); 存在しない場合はテーブルを作成します `book`( `bookid` INT(10) UNSIGNED NOT NULL 主キー AUTO_INCREMENT, `カード` INT (10) UNSIGNED NOT NULL ); クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 クラス(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 book(card)VALUES(FLOOR(1+(RAND()*20)))に挿入します。 mysql> book(card) にインデックス Y を作成します。 select * from book left join class on book.card=class.card; を説明します。 +----+-------------+--------+-----------+--------+-------+---------------+-------+-------+-------+--------+---------+----------------------------------------------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+--------+-----------+--------+-------+---------------+-------+-------+-------+--------+---------+----------------------------------------------------+ | 1 | SIMPLE | ブック | NULL | インデックス | NULL | Y | 4 | NULL | 20 | 100.00 | インデックスを使用 | | 1 | SIMPLE | クラス | NULL | ALL | NULL | NULL | NULL | NULL | 20 | 100.00 | where の使用; 結合バッファーの使用 (ブロック ネスト ループ) | +----+-------------+--------+-----------+--------+-------+---------------+-------+-------+-------+--------+---------+----------------------------------------------------+ セットに 2 行、警告 1 件 (0.00 秒) 大きな違いはなく、依然として完全なテーブル クエリであることがわかります。これは、2 つのテーブルが左結合でクエリされるためです。左側のテーブルは完全にクエリされる必要があります。この時点では、右側のテーブルにインデックスを作成するだけで十分です。 逆に、右側のリンクは左側のテーブルにインデックスされている必要があります。 適切なテーブルにインデックスを作成する クラスにインデックス Y を作成します。 select * from book left join class on book.card=class.card; を説明します。 +----+-------------+--------+-----------+---------+---------------+-------+---------+----------------+------+------------+-------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+--------+-----------+---------+---------------+-------+---------+----------------+------+------------+-------------+ | 1 | SIMPLE | ブック | NULL | インデックス | NULL | Y | 4 | NULL | 20 | 100.00 | インデックスを使用 | | 1 | SIMPLE | クラス | NULL | ref | Y | Y | 4 | db01.book.card | 1 | 100.00 | インデックスを使用 | +----+-------------+--------+-----------+---------+---------------+-------+---------+----------------+------+------------+-------------+ セットに 2 行、警告 1 件 (0.00 秒) 正しいテーブルは 1 回だけクエリされることがわかります。 。タイプはrefです 3つのテーブルの最適化存在しない場合はテーブルを作成します `phone`( `phoneid` INT(10) UNSIGNED NOT NULL 主キー AUTO_INCREMENT, `カード` INT (10) UNSIGNED NOT NULL )エンジン = INNODB; 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 電話(カード)にVALUES(FLOOR(1+(RAND()*20)))を挿入します。 まずすべてのインデックスを削除します 本のインデックス Y をドロップします。 クラスのインデックス Y を削除します。 説明: select * from class left join book on class.card=book.card left join phone on book.card=phone.card; +----+-------------+--------+-----------+--------+---------------+-------+-------+-------+----------+----------+----------------------------------------------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+--------+-----------+--------+---------------+-------+-------+-------+----------+----------+----------------------------------------------------+ | 1 | SIMPLE | クラス | NULL | ALL | NULL | NULL | NULL | NULL | 20 | 100.00 | NULL | | 1 | SIMPLE | book | NULL | ALL | NULL | NULL | NULL | NULL | 20 | 100.00 | where の使用; 結合バッファーの使用 (ブロック ネスト ループ) | | 1 | SIMPLE | phone | NULL | ALL | NULL | NULL | NULL | NULL | 20 | 100.00 | where の使用; 結合バッファーの使用 (ブロック ネスト ループ) | +----+-------------+--------+-----------+--------+---------------+-------+-------+-------+----------+----------+----------------------------------------------------+ セットに 3 行、警告 1 件 (0.00 秒) インデックスを作成する book(card)にインデックスyを作成します。 phone(card)にインデックスzを作成します。 説明: select * from class left join book on class.card=book.card left join phone on book.card=phone.card; +----+-------------+--------+------------+---------+---------------+-------+----------+----------------+------+------------+-------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+--------+------------+---------+---------------+-------+----------+----------------+------+------------+-------------+ | 1 | SIMPLE | クラス | NULL | ALL | NULL | NULL | NULL | NULL | 20 | 100.00 | NULL | | 1 | SIMPLE | book | NULL | ref | y | y | 4 | db01.class.card | 1 | 100.00 | インデックスを使用 | | 1 | SIMPLE | 電話 | NULL | ref | z | z | 4 | db01.book.card | 1 | 100.00 | インデックスを使用 | +----+-------------+--------+------------+---------+---------------+-------+----------+----------------+------+------------+-------------+ セットに 3 行、警告 1 件 (0.00 秒) インデックスが正常に作成されたことがわかります。 。 ただし、 クラス(card)にインデックスxを作成します。 説明: select * from class left join book on class.card=book.card left join phone on book.card=phone.card; +----+-------------+---------+-----------+----------+---------------+-------+----------+----------------+------+------------+-------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+---------+-----------+----------+---------------+-------+----------+----------------+------+------------+-------------+ | 1 | SIMPLE | クラス | NULL | インデックス | NULL | x | 4 | NULL | 20 | 100.00 | インデックスを使用 | | 1 | SIMPLE | book | NULL | ref | y | y | 4 | db01.class.card | 1 | 100.00 | インデックスを使用 | | 1 | SIMPLE | 電話 | NULL | ref | z | z | 4 | db01.book.card | 1 | 100.00 | インデックスを使用 | +----+-------------+---------+-----------+----------+---------------+-------+----------+----------------+------+------------+-------------+ セットに 3 行、警告 1 件 (0.00 秒) 結果は同じだ テーブルを作成 テーブルスタッフの作成( id INT 主キー AUTO_INCREMENT、 `name` VARCHAR(24)NOT NULL DEFAULT'' COMMENT'Name', `age` INT NOT NULL DEFAULT 0 COMMENT'年齢', `pos` VARCHAR(20) NOT NULL DEFAULT'' COMMENT'位置', `add_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT'ジョブエントリ時間' )CHARSET utf8 COMMENT'従業員記録テーブル'; staffs(`name`,`age`,`pos`,`add_time`) に VALUES('z3',22,'manager',NOW()) を挿入します。 staffs(`name`,`age`,`pos`,`add_time`) に VALUES('7月',23,'dev',NOW()) を挿入します。 staffs(`name`,`age`,`pos`,`add_time`) に VALUES('2000',23,'dev',NOW()) を挿入します。 インデックスを作成します。 ALTER TABLE staffs ADD INDEX index_staffs_nameAgePos(`name`,`age`,`pos`); インデックスのヒント
上の図から、名前を省略するとインデックスが使用できないことがわかります。 mysql> explain select * from staffs where name='july'; +----+-------------+----------+-----------+----------+--------------------------+--------------------------+--------+-------+-------+-------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+----------+-----------+----------+--------------------------+--------------------------+--------+-------+-------+-------+ | 1 | SIMPLE | スタッフ | NULL | ref | index_staffs_nameAgePos | index_staffs_nameAgePos | 74 | const | 1 | 100.00 | NULL | +----+-------------+----------+-----------+----------+--------------------------+--------------------------+--------+-------+-------+-------+ セットに 1 行、警告 1 件 (0.00 秒) mysql> explain select * from staffs where name='july' and pos='dev'; +----+-------------+----------+------------+----------+--------------------------+--------------------------+--------+--------+----------+-------------------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+----------+------------+----------+--------------------------+--------------------------+--------+--------+----------+-------------------------+ | 1 | SIMPLE | staffs | NULL | ref | index_staffs_nameAgePos | index_staffs_nameAgePos | 74 | const | 1 | 33.33 | インデックス条件の使用 | +----+-------------+----------+------------+----------+--------------------------+--------------------------+--------+--------+----------+-------------------------+ セットに 1 行、警告 1 件 (0.00 秒) ステートメントから、中間のインデックスをスキップした後も key_len は変更されないことがわかり、インデックス pos が使用されていないことが証明されます。
インデックスケースインデックス(a, b, c)を想定 Yはすべてのインデックスが使用されていることを意味し、Nはいずれも使用されていないことを意味します。
インデックス(a、b、c、d)を仮定します テーブルTest03を作成します( id int null auto_incrementではないプライマリキー、 int(10)、 b int(10)、 C int(10)、 D int(10)、 test03(a、b、c、d)値に挿入(3,4,5,6); test03(a、b、c、d)値に挿入(3,4,5,6); test03(a、b、c、d)値に挿入(3,4,5,6); test03(a、b、c、d)値に挿入(3,4,5,6); test03(a、b、c、d)でインデックスidx_test03_abcdを作成します。 ###
グループごとにグループごとに並べ替えます。 インデックス最適化による注文
exsitesAを選択します。 上記のクエリは、存在するa.length()の結果を実行します resultSet = []; for(int i = 0; i <a.length; i ++){if(exists(a [i] .id){// b.id = a.idからselect 1を実行してレコードがあるかどうかを確認します。 : : : : : : : : : : : : : : : MySQLスロークエリログコマンド「%slow_query_log%」などの変数を表示します。 MySQLスロークエリログを有効にするかどうかを示します グローバルslow_query_log = 0を設定します。 MySQLスロークエリログを閉じます グローバルslow_query_log = 1を設定します。 MySQLスロークエリログをオンにします '%long_query_time%'などの変数を表示します。 表示するのにどれくらい時間がかかりますか? グローバルlong_quert_time = 10を設定します。 遅いクエリ時間を10秒に変更します。 「%slow_queries%」などのグローバルステータスを表示します。 スロークエリステートメントの数を示します [root@iz0jlh1zn42cgftmrf6p6sz data]#cat mysql-slow.log LinuxクエリスローSQL 関数操作バッチ挿入データテーブル部を作成します( id int unsignedプライマリキーAuto_increment、 Deptno Mediunint unsigned Not Nullデフォルト0、 dname varchar(20)null default ''、 loc varchar(13)nullデフォルトではない '' )Engine = InnoDBデフォルトcharset = gbk; テーブルEMPを作成します( id int unsignedプライマリキーAuto_increment、 : : : : : : : : : : : : : : : 'log_bin_trust_function_creators'のような変数を表示します。 グローバルlog_bin_trust_function_creators = 1を設定します。
//関数1を定義します デリミッター$$ functionrand_string(n int)を作成するvarchar(255)を返します 始める 宣言chars_set varchar(100)デフォルト 'abcdefghigklmnopqrstuvwxyzabcdefghigklmnopqrstuvwxyz'; declare return_str varchar(255)default ''; declare i int default 0; 私がしますが set return_str = concat(return_str、substring(chars_set、floor(1 + rand()*52)、1)); i = i + 1を設定します。 while; return return_str; $$を終了します //関数2を定義します デリミッター$$ functionrand_num()returns int(5)を作成する 始める declare i int default 0; i = floor(100 + rand()*10)を設定します。 私を返します。 $$を終了します //ストアドプロシージャ1を定義します1 デリミッター$$ 手順insert_empを作成する(start int(10)、in max_num int(10)) 始める declare i int default 0; autocommit = 0を設定します。 繰り返す i = i + 1を設定します。 emp(empno、enname、job、mgr、hiredate、sal、comm、deptno)値((start + i)、rand_string(6)、 'salesman'、0001、curdate()、2000,400、rand_num()); i = max_numまで 繰り返し終了します。 専念; $$を終了します //ストアドプロシージャ2を定義します デリミッター$$ 手順insert_dept(start int(10)、in max_num int(10))を作成する 始める declare i int default 0; autocommit = 0を設定します。 繰り返す i = i + 1を設定します。 Insert Into Dept(deptno、dname、loc)values((start + i)、rand_string(10)、rand_string(8)); i = max_numまで 繰り返し終了します。 専念; $$を終了します // Data Delimiterを挿入します。 insert_dept(100,10)を呼び出します。 insert_emp(100001,500000)を呼び出します。 プロファイル分析SQLを表示しますmysql>「プロファイリング」などの変数を表示します。 +---------------------+ | variable_name | +---------------------+ |プロファイリング| +---------------------+ セット内の 1 行 (0.00 秒) mysql> set profiling = on; クエリOK、0行の影響を受ける、1つの警告(0.00秒) mysql>「プロファイリング」などの変数を表示します。 +---------------------+ | variable_name | +---------------------+ |プロファイリング| +---------------------+ セットの1列(0.01秒) いくつかの挿入ステートメントを書く クエリ操作ステートメントの速度を表示します mysql> showプロファイル。 +----------+------------+----------------------------------------------------------------+ | query_id | +----------+------------+----------------------------------------------------------------+ | | 0.00018850 | |。 | 0.00023900 | | 0.00031125 |。 |。 | 0.00023725 |。 | 8.00023825 |。 |。 |。 | 11 | .00024550 |。 |。 +----------+------------+----------------------------------------------------------------+ セットの12行、1つの警告(0.00秒) クエリプロセスSQLライフサイクルを表示します mysql> showプロファイルcpu、query 3のブロックio。 +----------------------+----------+----------+------------+--------------+---------------+ | +----------------------+----------+----------+------------+--------------+---------------+ | 0.000040 | | | |オープンテーブル| | Query End | |閉じるテーブル| | 0.000010 | | 0.000006 | +----------------------+----------+----------+------------+--------------+---------------+ セットの8行、1つの警告(0.00秒) mysql> showプロファイルcpu、query for query 12のブロックio。 +----------------------+----------+----------+------------+--------------+---------------+ | +----------------------+----------+----------+------------+--------------+---------------+ | | |オープンテーブル| | init | |システムロック| |最適化| | 0.000010 | | 0.000005 | | TMPテーブル| | 0.000001 | | | | | | Query End | | TMPテーブル| | Query End | | 0.000004 | | | 0.000004 | +----------------------+----------+----------+------------+--------------+---------------+ セットの20行、1つの警告(0.00秒) 上記の4つのいずれかが表示される場合、クエリステートメントを最適化する必要があります グローバルクエリロググローバルgeneral_log = 1を設定します。 グローバルlog_output = 'table'を設定します。 その後、あなたが書いたSQLステートメントは、MySQLライブラリのGeneral_logテーブルに記録されます select * from mysql.general_log; mysql> select * from mysql.general_log; +----------------------------+---------------------------+-----------+-----------+--------------+---------------------------------+ | event_time | +----------------------------+---------------------------+-----------+-----------+--------------+---------------------------------+ | 2021-12-06 11:53.457242 | +----------------------------+---------------------------+-----------+-----------+--------------+---------------------------------+ セット内の 1 行 (0.00 秒) mysqlロック
下のテストテーブルロック big_dataを使用してください。 テーブルMyLockを作成します( id int null primary key auto_increment、 名前varchar(20)デフォルト '' )エンジンmyisam; mylock(name)valuesに挿入( 'a'); mylock(name)valuesに挿入( 'b'); mylock(name)values( 'c')に挿入; mylock(name)valuesに挿入( 'd'); mylock(name)valuesに挿入( 'e'); mylockから *を選択します。 ロックコマンドロックテーブルmylock読み、本の書き込み; ##ロックmylock書き込みロックブックを読む 開いたテーブルを表示します##ロック解除テーブル; ##キャンセルロックを表示します テーブルロック:ロックを読み取ります##読み取りロックを追加した後、mysql>ロックテーブルmylock read; ## 1 クエリは正常、影響を受けた行は 0 行 (0.00 秒) mysql> select * from mylock; ## 1 +----+------+ | id | +----+------+ | | | 3 | | 4 | | 5 | +----+------+ セット内の行数は 5 です (0.00 秒) mysql> mylock set name = 'a2'ここで## 1; エラー1099(HY000):テーブル「MyLock」は読み取りロックでロックされていて、更新できません ##現在の読み取りロックによってロックされたテーブルを変更できません エラー1100(HY000):テーブル「本」はロックテーブルでロックされていません 2つのコマンドを区別するために、1は元のMySQLコマンド端末の操作と見なされ、2は新しく作成されたMySQL端末と見なされます 新しいMySQL端子コマンド操作を作成します ##新しいMySQLターミナルコマンド操作mysql> mylock set name = 'a3'を更新します ブロッキング操作が見つかります 元のMySQLコマンド端子のロックをキャンセルします テーブルのロックを解除; ## 1 クエリOK、1行の影響を受ける(2分1.46秒)## 2 一致する行:1変更:1警告:0 ## 2 あなたはそれが2分以上ブロックされていることがわかります 概要:ロックテーブルを読んだ後、MyLock:1。Query操作:現在のクライアント(ターミナルコマンド操作1)がクエリテーブルMyLockを実行できます 他のクライアント(ターミナルコマンド操作2)は、テーブルMyLock 2をクエリすることもできます。DML操作(追加、削除、および変更) テーブルロック:書き込みロックmysql>ロックテーブルmylock write; クエリは正常、影響を受けた行は 0 行 (0.00 秒) 現在のセッションに書き込みロックを追加しますmyLockテーブルmysql>更新mylock set name = 'a4'where id = 1; クエリOK、1行の影響を受ける(0.00秒) 一致する行:1の変更:1警告:0 mysql> select * from mylock; +----+------+ | id | +----+------+ | 1 | | | 3 | | 4 | | 5 | +----+------+ mysql> select * from book; エラー1100(HY000):テーブル「本」はロックテーブルでロックされていません 他のテーブルは操作できませんが、ロックされたテーブルを操作できることがわかります 新しいクライアントを開いて、ロックされたテーブルをテストします mysql> select * from mylock; セットの5列(2分30.92秒) 新しいクライアントの書き込みロックによってロックされたテーブルは、操作(追加、削除、変更、およびチェック)がブロックされるとブロックされることがわかりました。 する
mysql>「テーブル%」のようなステータスを表示します。 +---------------------------------+ | variable_name | +---------------------------------+ | | | | | +---------------------------------+ セット内の行数は 5 です (0.00 秒) 行ロックINNODBの行ロックモード INNODBは、次の2種類のラインロックを実装します。
更新、削除、およびステートメントを挿入するために、INNODBは、関係するデータセットに排他的ロック(x)を自動的に追加します。 通常の選択ステートメントの場合、InnoDBはロックを追加しません。 レコードセットは、次のステートメントを通じて共有ロックまたは排他的ロックで表示できます。 共有ロック(s):select * from table_name where ... lockin share mode 排他的ロック(x):select * from table_name where ... for update ラインロックはトランザクションをサポートしているため、こちらを確認してください トランザクショントランザクションは、SQLステートメントで構成される一連の論理処理ユニットです
同時トランザクションによって引き起こされる問題:
上記のトランザクションの並行性の問題を解決するために、データベースはこの問題を解決するための特定のトランザクション分離メカニズムを提供します。データベースのトランザクション分離が厳しくなるほど、並行性の副作用は小さくなりますが、トランザクションの分離は本質的に「シリアル化」されているため、価格が大きくなります。 データベースの4つの分離レベルがあります。低から高く、読み取り、読み取り、繰り返しの読み取り、およびシリアル化可能なものがあります。
注: MySQLデータベースのデフォルトの分離レベルは、再現可能な読み取り、表示方法です。 「tx_isolation」のような変数を表示します。 ロックテストテーブルの構築、ケースの準備作業 テーブルtest_innodb_lockを作成する( id int(11)、 名前varchar(16)、 セックスバルチャー(1) )Engine = InnoDBデフォルトcharset = utf8; test_innodb_lock値に挿入(1、 '100'、 '1'); test_innodb_lock値に挿入(3、 '3'、 '1'); test_innodb_lock値に挿入(4、 '400'、 '0'); test_innodb_lock値に挿入(5、 '500'、 '1'); test_innodb_lock値に挿入(6、 '600'、 '0'); test_innodb_lock値に挿入(7、 '700'、 '0'); test_innodb_lock値に挿入(8、 '800'、 '1'); test_innodb_lock値に挿入(9、 '900'、 '1'); test_innodb_lock値に挿入(1、 '200'、 '0'); Test_innodb_lock(id)でインデックスidx_test_innodb_lock_idを作成します。 index_innodb_lock_name on test_innodb_lock(name); ロックテスト自動トランザクションの提出がロックを自動的に追加してロックを解放するため、2つの端子テストを開きて自動トランザクションの送信をオフにすることをお勧めします。 mysql> set autocommit = 0; mysql> set autocommit = 0;
左を更新します mysql> update test_innodb_lock set name = '100'ここでid = 3; クエリは正常、影響を受けた行は 0 行 (0.00 秒) 一致する行:1変更:0警告:0 左を更新します 右側を更新した後、操作を停止します mysql>更新test_innodb_lock set name = '340' where id = 3; エラー1205(HY000):トランザクションを再起動してください ロックがリリースされるか、トランザクションがコミットされるまでブロックが実行されることがわかります。
他のトランザクションはこの声明の行を実行することはできませんが、他の行からデータを操作できます。
操作のパフォーマンス時にインデックスを使用することを忘れないでください:InnoDBエンジンインデックスの失敗タイムロックはテーブルロックにアップグレードされます mysql>更新test_innodb_lock set sex = '2' where name = 400; クエリは正常、影響を受けた行は 0 行 (0.00 秒) 一致する行:2の変更:0警告:0 この名前には、ここに単一の引用インデックスがないことに注意してください。 mysql> update test_innodb_lock set sex = '3' where id = 3; クエリOK、1行の影響を受ける(23.20秒) 一致する行:1の変更:1警告:0 私は、他の行操作もブロッキング状態に閉じ込められていることがわかりました。 もともとは、1列のデータのみをロックしていましたが、名前フィールドに単一の引用符を追加するのを忘れていたため、インデックスはすべてのテーブルをロックしました。 ギャップロックデータを取得し、共有または排他的なロックを要求する代わりに、この範囲の条件には存在しないレコードがあります mysql> select * from test_innodb_lock; +------+------+ | id | +------+------+ | 1 100 | | 3 | | 400 | | 500 | | 600 | | 700 | | 800 | | 900 | | +------+------+ ID2のデータはありません ロックの要求を確認してください mysql>「innodb_row_lock%」のようなステータスを表示します。 +------------------------------------+ | variable_name | +------------------------------------+ | | | | | +-----------------------------------+ セット内の行数は 5 です (0.00 秒) 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よりも高くないかもしれませんが、さらに悪いかもしれません。 最適化の提案:
以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: Docker での WSL の構成と変更の問題について
>>: MIME TYPEとは?MIME-Typesタイプコレクション
ウェブサイト体験の分類1. 感覚体験:快適性を重視した視聴覚体験をユーザーに提供します。 2. イン...
目次mysql フィルター レプリケーションメインデータベースに実装ライブラリから実装いくつかの質問...
1. 開発環境 vue+vant 2. コンピュータシステム Windows 10 Profess...
何が大問題ですか?長時間実行され、長時間コミットされないトランザクションは、大規模トランザクションと...
メタ宣言注釈の手順: 1. モバイル ページと 1 対 1 で対応するすべての PC ページを分類し...
コードは次のようになります。 。プロセス{ 境界線:1px 実線 #B7B7B8; 背景:#F8F8...
CSS は Web ページの印刷スタイルを制御します。 CSS を使用して印刷スタイルを制御します。...
目次一般的な配列メソッドconcat() メソッドjoin() メソッドpop() メソッドpush...
ネットワークが分離されているため、MySQL は yum を使用してインストールできません。ここでは...
01. VMware Workstation Pro 15 のダウンロードダウンロード: VMwa...
序文この記事では、Nginx の一般的な、実用的で興味深い構成をいくつか紹介します。この記事を読んだ...
目次1. 親コンポーネントが子コンポーネントにデータを渡す1.1. 親コンポーネントコード1.2. ...
さまざまな理由で、誰もが MySQL を再インストールする必要があると思います。 MySQL と Q...
エラーメッセージ:ユーザー: 'root' ホスト: `localhost'...
目次1. 親コンポーネントと子コンポーネント2. テンプレート分離書き込み1. テンプレートタグ2....