mysqlインデックスと一般的に使用される最適化方法の概要
1.インデックスの概要
インデックスは、データベースストレージエンジンがレコードをすばやく見つけるために使用するデータ構造です。データ量が膨大な場合、全表スキャンを回避し、検索の効率を高めます。たとえば、特定の本の特定のコンテンツを検索する場合、本全体をページごとに調べる方法は明らかに不器用です。したがって、私たちは通常、本のカタログインデックスに従って、本の特定の章の内容をすばやく見つけます。
私たちがよく使用するmysqlのinnoDBエンジンは、B-Treeインデックスの原則に基づいており、元のデータ形式に従って保存されます。
第二に、インデックスの長所と短所の
利点の使用:
- システムのプログラム効率を改善し、サーバーがテーブル全体をスキャンするために必要なデータの量を大幅に削減します
- サーバーがソートや一時テーブルを回避できるようにする
- ランダムI / OはシーケンシャルI / Oに変更できます。
欠点: - インデックスファイルを適宜更新する必要があるため、追加および削除操作の速度が低下します。
- メモリを増やす
ために、次の表を見ることができます。
CREATE TABLE `price_acct_bill_prod` (
`acct_bill_id` bigint(20) NOT NULL AUTO_INCREMENT,
`acct_date` varchar(10) NOT NULL COMMENT '账期yyyyMM',
`msisdn` varchar(16) NOT NULL COMMENT '产生费用的接入号',
`imsi` varchar(18) DEFAULT NULL COMMENT '号码对应的imsi',
`cust_id` bigint(20) DEFAULT NULL COMMENT '客户id',
`cust_name` varchar(255) DEFAULT NULL COMMENT '客户名称',
`account_id` bigint(20) NOT NULL COMMENT '账户id',
`expenses` decimal(16,0) NOT NULL COMMENT '账单费用',
`price_pro_nbr` varchar(30) DEFAULT NULL COMMENT '价格计划编码',
`usage_data` bigint(20) DEFAULT '0' COMMENT '使用流量',
`total_data` bigint(20) DEFAULT '0' COMMENT '累计流量',
`create_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
`update_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`status` int(11) DEFAULT '0' COMMENT '状态 0 :未销账 , 1: 已销账',
PRIMARY KEY (`acct_bill_id`),
KEY `msisdn` (`msisdn`),
KEY `imsi` (`imsi`),
KEY `cust_acct` (`cust_id`,`acct_date`) USING BTREE,
KEY `acct_date` (`acct_date`),
KEY `idx_iccid` (`iccid`)
) ENGINE=InnoDB AUTO_INCREMENT=71319084 DEFAULT CHARSET=utf8 COMMENT='账单';
上記の表には、主キーインデックス、ジョイントインデックス、通常のインデックスなど、多くのインデックスが追加されています。下の図から、インデックスメソッドがBTreeメソッドであることがわかります。
では、インデックスはどのくらいのメモリを消費しますか?下の写真を見てください。まず、テーブルには3,000万個以上のデータがあり、データは約9Gを占め、インデックスは約7Gを占めています。
3つ、インデックスの追加に適したフィールド
この質問に答える前に、インデックスがSQLパフォーマンスの最良のソリューションであるかどうかという質問があります。「HighPerformanceMysq」の回答を参照してください。
インデックスを使用することによるパフォーマンス上の利点が、それ自体で消費されるパフォーマンスよりも大きい場合にのみ、インデックスを使用する価値があります。非常に小さいテーブルの場合、インデックスを使用するよりも単純な全表スキャンの方が効率的です。一般的な中規模および大規模のテーブルの場合、インデックスは非常に効果的です。ただし、非常に大きなテーブルの場合、インデックスの確立と使用のコストも増加します。この場合、1つのレコードを1つのレコードと照合するのではなく、クエリに必要なデータのセットを直接区別するテクノロジーが必要です。たとえば、パーティショニングテクノロジを使用できます。
では、どのフィールドがインデックス作成に適していますか?
1.表的主键:很多时候我们都会根据主键的id去查询某条数据,自增主键就是主键索引
2.查询次数比较多,值有很多的列。比如有个用户表:userId就可以设置成主键,而用户的性别就没啥必要
インデックスの種類は何ですか?
1.主键索引
2.普通索引
3.唯一索引
4.联合(组合)索引
第四に、クエリを最適化する方法
- MySQLインデックスは、左マッチングの原則です。たとえば、ユーザーテーブルには(名前、電話)と通常のインデックス(会社)の共同インデックスがあります。
-- 走索引的情况
select * from user where name = "tom" 走联合索引
select * from user where name = "tom" and phone = "13222220000" 走联合索引
select * from user where phone = "13222220000" and name = "tom" 走联合索引
select * from user where company like "alibaba%" 走普通索引
-- 不走索引的情况
select * from user where phone = "13222220000" 不走索引
select * from user where company like "%alibaba" 不走索引
- 独立した列、アセンブルできないクエリ条件
select * from user where company + "abc" ="libabaabc" 不走索引
- クエリ条件でまたはを使用する場合、条件にインデックスを付ける必要があります。インデックスのない条件がある限り、インデックスクエリは使用されません。
- ヌルかどうかを判断する
select * from user where company is null 走索引
select * from user where company = null 不走索引
- group byはインデックスを使用せず、全表スキャンです
- グループ化は効率を改善したいので、ソートは禁止されており、最後にnullによる順序が追加されます。改善された効率は制限されます。
- > =を使用せず、>を直接使用します
5.特定のクエリSQLにインデックスが付けられているかどうかを判断するにはどうすればよいですか?実行プラン:
直接説明:explain + sql上記の
図のインデックス実行構造を表示:type = ref、key = name、これは、このsqlクエリがインデックスを使用し、名前がインデックスであることを意味します。
以下は、次のない状況をシミュレートします。インデックス:
type = ALL:全表スキャン、key = Null、インデックスは取得されないことを意味します。