实战:
创建一张表index_test
CREATE TABLE `index_test` (
`id` bigint(20) NOT NULL COMMENT '主键',
`uuid` varchar(64) NOT NULL COMMENT 'uuid(orderId_skuId)',
`order_id` bigint(20) NOT NULL COMMENT '订单号',
`order_amount` bigint(20) NOT NULL COMMENT '订单金额',
`merchant_code` varchar(32) NOT NULL COMMENT '商家码',
`merchant_name` varchar(32) NOT NULL COMMENT '商家名称',
`created` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_uuid` (`uuid`),
KEY `index_order_id` (`order_id`),
KEY `index_id_merchant_name` (`id`,`merchant_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='索引测试表';
如果这张表创建在弹性库中,如果遇到下面SQL会出现性能问题。
我们都知道弹性库需要使用路由字段比如 merchant_code将数据存放到多个分片中(多个数据库中),弹性库优点是我们不用担心扩容问题,我们再也不用分库分表。缺点你的SQL语句不够优秀会导致查询效率非常慢。
举个例子
查询商户下所有订单号和订单金额
比如 select order_id,order_amount from index_test where id>0 and merchant_name='test' order by id desc
为什么使用id>0?
回答: 为了进行分页(这只是例子不需要较真)
当我们执行 explain select order_id,order_amount from index_test where id>0 and merchant_name='test' order by id desc
你会发现 possible_keys 显示 PRIMARY, index_id_merchant_name也就是 索引引擎可能使用两个索引
同一个语句在不同分片上最终引擎使用的索引可能不同。
为什么呢? 因为可能用到的索引有两个,那么每个分片可能查询的结果集不同,索引擎会选择自己认为最优的。很有可能选择的不是同一个索引,比如:一个分片查询的结果集用10万,这个分片数据有11万 那么这个分片可能会用 primary索引,因为数据结果集太多用primary比较合适,这个时候我们认为index_id_merchant_name 应该是最优的。
这个时候我们需要对语句添加force index 强制使用特定索引 提升SQL查询性能。
select order_id,order_amount from index_test froce index(index_id_merchant_name) where id>0 and merchant_name='test' order by id desc
这个写法有一定缺点就是某天 index_id_merchant_name索引删除 SQL会报错 需要注意