Mysql索引与 Sql语句优化

表例子


CREATE TABLE IF NOT EXISTS `order` (
  `id` int UNSIGNED NOT NULL COMMENT '订单编号',
  `buyer_id` int UNSIGNED NOT NULL COMMENT '买家编号',
  `seller_id` int UNSIGNED NOT NULL COMMENT '卖家编号',
  `goods_id` int UNSIGNED NOT NULL COMMENT '商品编号',
  `quantity` int UNSIGNED NOT NULL COMMENT '购买数量',
  `price` decimal(14,8) NOT NULL COMMENT '订单交易费', #此订单交易费
  `status` enum('CREATED','CANCELED','PAID','COMPLETED') DEFAULT 'CREATED' COMMENT '订单状态',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `edit_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `i1` (`buyer_id`,`seller_id`,`goods_id`),
  KEY `i2` (`quantity`),
  KEY `i3` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单表';

索引

  • InnoDB和 MyISAM引擎都是使用 B+树(B+Tree)作为索引结构.

关于表设计(DDL)中创建索引

  • 常用于(条件/排序/分组)的重复度比较低, 且基本不会更改的字段一般会设置索引, 主要是为了提高搜索性能
  • 索引会引起表容量增大, 且会直接降低增删改操作的性能, 所以每建一个索引需要做充分考虑, 建议一个表最好不要超过6个
  • 每当执行查询语句时 Mysql基本只会用到一个索引, 所以频次高的联合条件字段尽可能建成复合索引. 如: KEY i1(buyer_id,seller_id,goods_id)此复合索引, 等于建了3个索引1.(buyer_id,seller_id,goods_id), 2.(buyer_id,seller_id), 3.(buyer_id)
  • 需要建索引的字段, 最好是 NOT NULL, 条件中判断 NULL, 会导致索引失效
  • 需要值唯一的字段一定要创建 UNIQUE KEY(唯一索引)或主键设置 PRIMARY KEY
  • 由于 InnoDB的数据文件的数据存储结构是按主键聚集的方式, 所以表设计一定要有主键, 如果未设置, 系统会自动选择一个唯一标识或找不到此类列, 会隐式生成整型主键. 还有 InnoDB的数据文件本身就是 B+Tree索引结构, 每当插入删除数据时都会频繁的分裂调整, 因此建议主键最好是数值类型

条件中建有索引的字段, 导致索引失效语句

  1. 字段使用函数, 会导致索引失效. 例: YEAR(create_time)=2019
  2. 字段进行表达式操作, 会导致索引失效. 例: quantity/2=4
  3. 与赋的值类型不同导致自动类型转换, 索引会被失效. 例: buyer_id=“1”, 值为数值类型应该把双引号去掉 buyer_id=1
  4. 判断是否为 NULL, 会导致索引失效. 例: create_time IS NULL
  5. 使用 IN操作符, 会导致索引失效. 例: buyer_id IN (1,2,3). 建议使用 EXISTS操作符代替或, 如果是连续的数值, 可以使用 BETWEEN 1 AND 3代替
  6. 使用 NOT IN操作符, 会导致索引失效. 例: buyer_id NOT IN (4,6). 建议使用 NOT EXISTS操作符代替
  7. 使用 !=<>操作符, 会导致索引失效. 例: buyer_id!=3或 buyer_id<>3, 可以代替操作符为 SELECT ? FROM order WHERE buyer_id>3 UNION SELECT ? FROM order WHERE buyer_id<3
  8. 使用 OR操作符, 也会导致索引失效. 也建议使用 UNION代替
  9. 使用 LIKE操作符, 做模糊查询时, 如 quantity LIKE ‘%?’. %放到首位也会导致索引失效, 而进行全表扫描, 如果能预知开始位数比如前三位是未知的 quantity LIKE ‘___?’
  • 从版本 5.7.6开始, 搜索字符型字段可以使用 ngram全文解析, 比起 LIKE操作符, 效率好很多, 但数据量如果是百万,千万级别最好还是通过 Elastic Search, Apache Lucene或 Sphinx等 搜索引擎来实现.

其它

  1. 在分组查询时, 会默认进行排序, 如果不需要可以防止自动排序 GROUP BY后加 ORDER BY NULL

如果您觉得有帮助,欢迎点赞哦 ~ 谢谢!!

发布了62 篇原创文章 · 获赞 325 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qcl108/article/details/103658215