典型的なプロジェクト ケース 12 — mysql データベースのデータ型とテーブル フィールドの型の間の不一致により、インデックスが失敗する

1:背景紹介

mysql データベースの 2 つのテーブルのクエリ速度は非常に遅く、1 つのテーブルには 76015 データがあり、もう 1 つのテーブルには 217069 データがあります。データ型とテーブル フィールド型の不一致により、型変換が必要になり、インデックスの無効化がクエリ速度の低下につながると推測されます。
ここに画像の説明を挿入
ここに画像の説明を挿入

2: アイデアとソリューション

アイデアや計画を策定する前に、mysql のデータ型について学びましょう。
MySQLのデータ型、数値型、文字型、 日付時刻型、 バイナリ型
、数値型、整数型、浮動小数点数型の4種類に分けられます。

値のタイプ

タイプ 例証する サイズ (バイト) メモリ範囲 (符号なし) ストレージ範囲 (署名付き)
TINYINT 非常に小さい整数 1 0 〜255 -128〜127
SMALLINT 小整数 2 0〜65535 -32768〜32767
ミディアムミント 中型整数 3 0〜16777215 -8388608〜8388607
INT (INTEGHR 通常サイズの整数 4 0〜4294967295 -2147483648〜2147483647
BIGINT 大整数 8 0〜18446744073709551615 -9223372036854775808〜9223372036854775807
浮く 単精度浮動小数点 4 0 と 1.175494351E-38~3.402823466E+38 -3.402823466E+38~1.175494351E-38
ダブル 倍精度浮動小数点 8 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)
10 進数 (M、D)、DEC 圧縮された「厳密な」固定小数点数 M+2

DECIMAL の記憶領域は固定されていませんが、M+2 バイトを占有する精度値 M によって決定されます。

注: MySQL では、固定小数点数は文字列の形式で格納されます. 精度要件が比較的高い場合 (通貨や科学データなど), DECIMAL 型を使用することをお勧めします. 減算や減算も簡単に実行できます.他の 2 つの浮動小数点数の比較演算何かがうまくいかないので、浮動小数点数を使用するときは注意が必要であり、浮動小数点数の比較を避けるようにしてください。

日時型

タイプ 例証する サイズ (バイト)
年値 1
時間 時間値または期間 3
日にち 日付値 3
日付時刻 日付と時刻の混合値 8
タイムスタンプ 日付と時刻の混合値、タイムスタンプ 4

文字列型

タイプ 例証する サイズ (バイト)
魅力) 固定長の非バイナリ文字列 M バイト、1<=M<=255
VARCHAR(M) 可変長の非バイナリ文字列 L+1 バイト、ここでは L<=M および 1<=M<=255
小さなテキスト 非常に小さな非バイナリ文字列 L+1 バイト、ここでは L<2^8
文章 小さな非バイナリ文字列 L+2 バイト、ここでは L<2^16
中文 中規模の非バイナリ文字列 L+3 バイト、ここでは L<2^24
ロングテキスト 大きな非バイナリ文字列 L+4 バイト、ここでは L<2^32
列挙型 列挙型。列挙文字列値を 1 つだけ持つことができます 列挙値の数に応じて、1 または 2 バイト (最大は 65535)
設定 SET、String オブジェクトは 0 個以上の SET メンバーを持つことができます セットメンバーの数に応じて、1、2、3、4、または 8 バイト (最大 64 メンバー)

注: VARCHAR 型と TEXT 型は可変長型であり、それらのストレージ要件は、型の可能な最大サイズではなく、列値の実際の長さ (前の表では L で示されています) によって異なります。

たとえば、VARCHAR(10) 列には最大長 10 文字の文字列を格納できますが、実際のストレージには、文字列の長さ L に文字列の長さを記録するための 1 バイトを加えたものが必要です。文字「abcd」の場合、L は 4 で、ストレージには 5 バイトが必要です。

バイナリ型

タイプ 例証する サイズ (バイト)
ビット(M) ビットフィールド型 約 (M+7)/8 バイト
バイナリ(M) 固定長バイナリ文字列 M バイト
バービナリー(M) 可変長バイナリ文字列 M+1 バイト
タイニブロブ (M) 非常に小さな塊 8
ブロブ(M) 小さなブロブ L+2 バイト、ここで L<2^16
ミディアムブロブ (M) ミディアム BLOB L+3 バイト、ここで L<2^24
肺ブロブ (M) 非常に大きな塊 L+4 バイト、ここで L<2^32

問題の再発

テーブル インデックス
ここに画像の説明を挿入
テーブル フィールド タイプ
ここに画像の説明を挿入
クエリ ステートメント
クエリに数値型を使用

EXPLAIN
		SELECT * FROM arpro_chapter_template 
		WHERE
			is_delete	=0
			AND 
			active_id=385538879022694400

その結果、
インデクスが無効になり、
型式が全テーブルクエリに変更され、インデクスが無効になっていることがわかります。
ここに画像の説明を挿入
文字列型のクエリを使用する

		EXPLAIN
		SELECT * FROM arpro_chapter_template 
		WHERE
			is_delete	='0'
			AND 
			active_id=385538879022694400
			

結果
インデックスが有効になります
ここに画像の説明を挿入

結論は

数値型変換を行うと、インデックスが無効になります。補足: mysql は文字列と数値の比較に遭遇すると、デフォルトで文字列を数値型に変換します。そのため、is_delete の型が数値型の場合、sql によって割り当てられたデータ型が文字列の場合、と入力すると、インデックスは失敗しません。

SQL文に値を代入するときも含めて、エンティティの設計を行っています。データベースのデータ型を維持し、一貫性のないデータ型によるインデックスの失敗を避けることが最善です。

3.拡張

インデックスの失敗を要約する

インデックス列に計算があります

次のように sql を実行します。

		EXPLAIN
		SELECT * FROM arpro_chapter_template 
		WHERE
		is_delete+1=1
		

フル テーブル スキャンになっており、インデックス列に計算があり、インデックスが無効になっていることがわかります。計算された値ではなく、列の元の値がインデックスに格納されるためです。
ここに画像の説明を挿入

インデックスでの関数の使用

インデックス列に関数を追加します。SQL は次のとおりです。

		EXPLAIN
		SELECT * FROM arpro_chapter_template 
		WHERE
		SUM(is_delete)=1

全表スキャンのプログラミング、索引障害。計算された値ではなく、列の元の値がインデックスに格納されるためです。
ここに画像の説明を挿入

インデックスの暗黙的な型変換

1. インデックス フィールドが文字型で、条件クエリ中に整数型が渡された場合、インデックス エラーの問題が発生します。
2. インデックスが整数型で、条件クエリ中に文字型が渡された場合、インデックス エラーの問題は発生しません。
mysq が文字列と数値の比較に遭遇すると、デフォルトで文字列を数値型に変換します。そのため、is_delete の型が数値型の場合、SQL によって割り当てられたデータ型が文字列型の場合、その場合、インデックスは失敗します。

上記のケースは実践されており、実証されていません。

残りのインデックスが失敗した場合、それらは後で補充されます

4: まとめ

1. データベースを扱うときは、データ型が対応しているかどうかに特に注意を払う必要があり、データ型の不一致の影響を無視することはできません。
2. 開発過程でのインデックスの失敗を避けるために、インデックスを使用しない場合と使用する場合の効率はまったく異なります。

5: 昇華

ブログをまとめていく過程で、理不尽を打ち破り、理性陣営の一歩を踏み出しました。
ケースごとに練習と検証が行われています。

おすすめ

転載: blog.csdn.net/wangwei021933/article/details/129557554