订单的表结构采用了垂直分表的策略,将订单相关的不同模块的字段维护在不同表中

在订单处理这个页面,需要查询各种维度,

因此为了方便查询创建了v_sale_order视图(老版本)

drop view v_sale_order;
CREATE
VIEW `v_sale_order` AS
SELECT
`so`.`sale_order_id` AS `v_sale_order_id`,
`so`.`sale_order_id` AS `sale_order_id`,
`so`.`sale_order_no` AS `sale_order_no`,
`so`.`order_type` AS `order_type`,
`so`.`platform_order_code2` AS `platform_order_code2`,
`so`.`platform_order_code` AS `platform_order_code`,
`so`.`platform_type` AS `platform_type`,
`so`.`platform_order_status` AS `platform_order_status`,
`so`.`created` AS `created`,
`so`.`end_time` AS `end_time`,
`so`.`total_num` AS `total_num`,
`so`.`total_sku` AS `total_sku`,
`so`.`modified` AS `modified`,
`so`.`seller_flag` AS `seller_flag`,
`so`.`seller_memo` AS `seller_memo`,
`so`.`seller_rate` AS `seller_rate`,
`so`.`snapshot_url` AS `snapshot_url`,
`so`.`status` AS `status`,
`so`.`step_trade_status` AS `step_trade_status`,
`so`.`trade_from` AS `trade_from`,
`so`.`trade_memo` AS `trade_memo`,
`so`.`trade_source` AS `trade_source`,
`so`.`type` AS `type`,
`so`.`shop_id` AS `shop_id`,
`so`.`origin_type` AS `origin_type`,
`so`.`sys_promotion_info` AS `sys_promotion_info`,
`sor`.`buyer_area` AS `buyer_area`,
`sor`.`buyer_email` AS `buyer_email`,
`sor`.`buyer_ip` AS `buyer_ip`,
`sor`.`buyer_memo` AS `buyer_memo`,
`sor`.`buyer_message` AS `buyer_message`,
`sor`.`buyer_nick` AS `buyer_nick`,
`sor`.`buyer_rate` AS `buyer_rate`,
`sor`.`receiver_address` AS `receiver_address`,
`sor`.`receiver_city` AS `receiver_city`,
`sor`.`receiver_country` AS `receiver_country`,
`sor`.`receiver_district` AS `receiver_district`,
`sor`.`receiver_mobile` AS `receiver_mobile`,
`sor`.`receiver_name` AS `receiver_name`,
`sor`.`receiver_phone` AS `receiver_phone`,
`sor`.`receiver_state` AS `receiver_state`,
`sor`.`receiver_town` AS `receiver_town`,
`sor`.`receiver_zip` AS `receiver_zip`,
`sor`.`area_id` AS `area_id`,
`sor`.`customer_id` AS `customer_id`,
`soc`.`courier_id` AS `courier_id`,
`soc`.`courier_order_no` AS `courier_order_no`,
`soc`.`courier_print_mark_state` AS `courier_print_mark_state`,
`soc`.`courier_print_time` AS `courier_print_time`,
`sof`.`alipay_id` AS `alipay_id`,
`sof`.`alipay_no` AS `alipay_no`,
`sof`.`payment` AS `payment`,
`sof`.`total_fee` AS `total_fee`,
`soi`.`invoice_order_no` AS `invoice_order_no`,
`soi`.`invoice_content` AS `invoice_content`,
`soi`.`invoice_type` AS `invoice_type`,
`soi`.`bank` AS `bank`,
`soi`.`title` AS `title`,
`soi`.`bank_account` AS `bank_account`,
`soi`.`tariff_lines` AS `tariff_lines`,
`sos`.`oms_process_type` AS `oms_process_type`,
`sos`.`play_state` AS `play_state`,
`sos`.`pause_state` AS `pause_state`,
`sos`.`stop_state` AS `stop_state`,
`sos`.`archive_state` AS `archive_state`,
`sos`.`is_paid` AS `is_paid`,
`sos`.`is_checked` AS `is_checked`,
`sos`.`is_approved` AS `is_approved`,
`sos`.`is_suspended` AS `is_suspended`,
`sos`.`is_invalidated` AS `is_invalidated`,
`sos`.`is_to_be_shipped` AS `is_to_be_shipped`,
`sos`.`is_after_sale` AS `is_after_sale`,
`sos`.`is_split` AS `is_split`,
`sos`.`is_combined` AS `is_combined`,
`sos`.`is_closed` AS `is_closed`,
`sos`.`is_after_sale_closed` AS `is_after_sale_closed`,
`sos`.`is_amount_changed` AS `is_amount_changed`,
`sos`.`is_part_changed` AS `is_part_changed`,
`sos`.`is_out_of_stock` AS `is_out_of_stock`,
`sos`.`pay_type` AS `pay_type`,
`sos`.`pay_time` AS `pay_time`,
`sos`.`original_order_id` AS `original_order_id`,
`sos`.`after_sale_note` AS `after_sale_note`,
`sos`.`suspend_note` AS `suspend_note`,
`sos`.`unapprove_note` AS `unapprove_note`,
`sos`.`after_sale_type` AS `after_sale_type`,
`sos`.`blacklist_type` AS `blacklist_type`,
`sow`.`warehouse_id` AS `warehouse_id`,
`sow`.`retry_num` AS `retry_num`,
`sow`.`out_warehouse_time` AS `out_warehouse_time`,
`sow`.`purchase_order_no` AS `purchase_order_no`,
`sow`.`purchase_order_id` AS `purchase_order_id`,
`sow`.`wms_order_state` AS `wms_order_state`,
`sow`.`checked_time` AS `checked_time`,
`so`.`creator` AS `creator`,
`so`.`create_time` AS `create_time`,
`so`.`last_updater` AS `last_updater`,
`so`.`last_update_time` AS `last_update_time`,
`so`.`is_usable` AS `is_usable`,
`so`.`tenant_id` AS `tenant_id`
FROM
(
(
(
(
(
(
`sale_order` `so`
LEFT JOIN `sale_order_receiver` `sor` ON (
(
`so`.`sale_order_id` = `sor`.`sale_order_id`
)
)
)
LEFT JOIN `sale_order_status` `sos` ON (
(
`so`.`sale_order_id` = `sos`.`sale_order_id`
)
)
)
LEFT JOIN `sale_order_warehouse` `sow` ON (
(
`so`.`sale_order_id` = `sow`.`sale_order_id`
)
)
)
LEFT JOIN `sale_order_courier` `soc` ON (
(
`so`.`sale_order_id` = `soc`.`sale_order_id`
)
)
)
LEFT JOIN `sale_order_invoice` `soi` ON (
(
`so`.`sale_order_id` = `soi`.`sale_order_id`
)
)
)
LEFT JOIN `sale_order_finance` `sof` ON (
(
`so`.`sale_order_id` = `sof`.`sale_order_id`
)
)
);

之前的代码(老版本):

@Service
public class OrderService extends TemplateService { public static final String DEFALUT_FILTER = " AND NOT(is_split = 1 AND archive_state=3) AND NOT(is_combined = 1 AND archive_state=4) " +
" AND NOT(oms_process_type =0) AND (v_sale_order.platform_order_status != 'TRADE_FINISHED' OR origin_type=2) " +
"AND NOT is_invalidated=1" +
" AND NOT archive_state=5 AND NOT archive_state=6";
public static final String HISTORY_FILTER = " AND NOT(is_split = 1 AND archive_state=3) AND NOT(is_combined = 1 AND archive_state=4) " +
        " AND NOT archive_state=5 AND NOT archive_state=6"; }

DEFAULT_FILTER是订单处理里面,固定的查询条件,每次查询都会有该部分条件,但是sql的写法包含了太多OR,NOT,!= 等操作

优化第一步:  根据业务规则合并一些字段,将一些排除条件改为正向命中的条件(第二版):

@Service
public class OrderService extends TemplateService { /**
订单处理:
过滤掉:合并拆分的订单
过滤掉:交易完成或交易关闭
要求:跑过预处理
要求:已付款或者货到付款
要求:未作废的
*/
public static final String DEFALUT_FILTER = " AND archive_state IN (0, 1) AND v_sale_order.is_paid = 1 AND oms_process_type = 1 " +
" AND v_sale_order.is_invalidated=0 AND is_closed = 0";
/**
* 订单查询:
* 过滤掉:合并拆分的订单
*/
public static final String HISTORY_FILTER = " AND archive_state IN (0, 1)";
public static final String AFTER_FILTER = " AND archive_state IN (0,1,2) AND is_paid=1";
}

优化第二步:   订单处理相比订单查询多了很多固定条件,大部分处于sale_order_status表中,但是之前视图的创建方式固定了最左边的表,因此修改视图创建的脚本,如下:

从固定的left join改为 Join

CREATE OR REPLACE VIEW v_sale_order AS
SELECT
`so`.`sale_order_id` AS `v_sale_order_id`,
`so`.`sale_order_id` AS `sale_order_id`,
`so`.`sale_order_no` AS `sale_order_no`,
`so`.`order_type` AS `order_type`,
`so`.`platform_order_code2` AS `platform_order_code2`,
`so`.`platform_order_code` AS `platform_order_code`,
`so`.`platform_type` AS `platform_type`,
`so`.`platform_order_status` AS `platform_order_status`,
`so`.`created` AS `created`,
`so`.`end_time` AS `end_time`,
`so`.`total_num` AS `total_num`,
`so`.`total_sku` AS `total_sku`,
`so`.`modified` AS `modified`,
`so`.`seller_flag` AS `seller_flag`,
`so`.`seller_memo` AS `seller_memo`,
`so`.`seller_rate` AS `seller_rate`,
`so`.`snapshot_url` AS `snapshot_url`,
`so`.`status` AS `status`,
`so`.`step_trade_status` AS `step_trade_status`,
`so`.`trade_from` AS `trade_from`,
`so`.`trade_memo` AS `trade_memo`,
`so`.`trade_source` AS `trade_source`,
`so`.`type` AS `type`,
`so`.`shop_id` AS `shop_id`,
`so`.`origin_type` AS `origin_type`,
`so`.`sys_promotion_info` AS `sys_promotion_info`,
`sor`.`buyer_area` AS `buyer_area`,
`sor`.`buyer_email` AS `buyer_email`,
`sor`.`buyer_ip` AS `buyer_ip`,
`sor`.`buyer_memo` AS `buyer_memo`,
`sor`.`buyer_message` AS `buyer_message`,
`sor`.`buyer_nick` AS `buyer_nick`,
`sor`.`buyer_rate` AS `buyer_rate`,
`sor`.`receiver_address` AS `receiver_address`,
`sor`.`receiver_city` AS `receiver_city`,
`sor`.`receiver_country` AS `receiver_country`,
`sor`.`receiver_district` AS `receiver_district`,
`sor`.`receiver_mobile` AS `receiver_mobile`,
`sor`.`receiver_name` AS `receiver_name`,
`sor`.`receiver_phone` AS `receiver_phone`,
`sor`.`receiver_state` AS `receiver_state`,
`sor`.`receiver_town` AS `receiver_town`,
`sor`.`receiver_zip` AS `receiver_zip`,
`sor`.`area_id` AS `area_id`,
`sor`.`customer_id` AS `customer_id`,
`soc`.`courier_id` AS `courier_id`,
`soc`.`courier_order_no` AS `courier_order_no`,
`soc`.`courier_print_mark_state` AS `courier_print_mark_state`,
`soc`.`courier_print_time` AS `courier_print_time`,
`sof`.`alipay_id` AS `alipay_id`,
`sof`.`alipay_no` AS `alipay_no`,
`sof`.`payment` AS `payment`,
`sof`.`total_fee` AS `total_fee`,
`soi`.`invoice_order_no` AS `invoice_order_no`,
`soi`.`invoice_content` AS `invoice_content`,
`soi`.`invoice_type` AS `invoice_type`,
`soi`.`bank` AS `bank`,
`soi`.`title` AS `title`,
`soi`.`bank_account` AS `bank_account`,
`soi`.`tariff_lines` AS `tariff_lines`,
`sos`.`oms_process_type` AS `oms_process_type`,
`sos`.`play_state` AS `play_state`,
`sos`.`pause_state` AS `pause_state`,
`sos`.`stop_state` AS `stop_state`,
`sos`.`archive_state` AS `archive_state`,
`sos`.`is_paid` AS `is_paid`,
`sos`.`is_checked` AS `is_checked`,
`sos`.`is_approved` AS `is_approved`,
`sos`.`is_suspended` AS `is_suspended`,
`sos`.`is_invalidated` AS `is_invalidated`,
`sos`.`is_to_be_shipped` AS `is_to_be_shipped`,
`sos`.`is_after_sale` AS `is_after_sale`,
`sos`.`is_split` AS `is_split`,
`sos`.`is_combined` AS `is_combined`,
`sos`.`is_closed` AS `is_closed`,
`sos`.`is_after_sale_closed` AS `is_after_sale_closed`,
`sos`.`is_amount_changed` AS `is_amount_changed`,
`sos`.`is_part_changed` AS `is_part_changed`,
`sos`.`is_out_of_stock` AS `is_out_of_stock`,
`sos`.`pay_type` AS `pay_type`,
`sos`.`pay_time` AS `pay_time`,
`sos`.`original_order_id` AS `original_order_id`,
`sos`.`after_sale_note` AS `after_sale_note`,
`sos`.`suspend_note` AS `suspend_note`,
`sos`.`unapprove_note` AS `unapprove_note`,
`sos`.`after_sale_type` AS `after_sale_type`,
`sos`.`blacklist_type` AS `blacklist_type`,
`sow`.`warehouse_id` AS `warehouse_id`,
`sow`.`retry_num` AS `retry_num`,
`sow`.`out_warehouse_time` AS `out_warehouse_time`,
`sow`.`purchase_order_no` AS `purchase_order_no`,
`sow`.`purchase_order_id` AS `purchase_order_id`,
`sow`.`wms_order_state` AS `wms_order_state`,
`sow`.`checked_time` AS `checked_time`,
`so`.`creator` AS `creator`,
`sos`.`create_time` AS `create_time`,
`so`.`last_updater` AS `last_updater`,
`sos`.`last_update_time` AS `last_update_time`,
`sos`.`is_usable` AS `is_usable`,
`sos`.`tenant_id` AS `tenant_id`
FROM ((((((`sale_order_status` `sos`
JOIN `sale_order_receiver` `sor` ON ((`sos`.`sale_order_id` = `sor`.`sale_order_id`))) JOIN
`sale_order` `so` ON ((`so`.`sale_order_id` = `sos`.`sale_order_id`))) JOIN
`sale_order_warehouse` `sow` ON ((`sos`.`sale_order_id` = `sow`.`sale_order_id`))) JOIN
`sale_order_courier` `soc` ON ((`sos`.`sale_order_id` = `soc`.`sale_order_id`))) JOIN
`sale_order_finance` `sof` ON ((`sos`.`sale_order_id` = `sof`.`sale_order_id`))) LEFT JOIN
`sale_order_invoice` `soi` ON ((`sos`.`sale_order_id` = `soi`.`sale_order_id`)))

最左边表可根据查询条件动态的变化,(如条件过滤查询sale_order_courier的courier_id字段, where courier_id= xx,并且sale_order_courier的courier_id字段上已经建立了索引,那么explain后第一个查询的表就是sale_order_courier)

之前sale_order表始终作为v_sale_order实际查询时的第一个表,而无法走索引

(P.S.本人目前的理解:mysql多表关联查询只有最左边表可以走索引,其余表的索引只能是关联的id作为索引)

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE sos ref idx_sale_order_id,oms_normal_v2,oms_check_v2,oms_suspend_v2 oms_check_v2 10 const,const,const,const 271 Using where; Using filesort
1 SIMPLE sor ref idx_sale_order_id idx_sale_order_id 9 egenie.sos.sale_order_id 1 NULL
1 SIMPLE soc ref idx_sale_order_id idx_sale_order_id 9 egenie.sos.sale_order_id 1 NULL
1 SIMPLE sof ref idx_sale_order_id idx_sale_order_id 9 egenie.sos.sale_order_id 1 NULL
1 SIMPLE so eq_ref PRIMARY PRIMARY 8 egenie.sos.sale_order_id 1 NULL
1 SIMPLE sow ref idx_sale_order_id idx_sale_order_id 9 egenie.sos.sale_order_id 1 NULL
1 SIMPLE soi ref idx_sale_order_id idx_sale_order_id 9 egenie.sos.sale_order_id 1 NULL

随后创建的索引(第一版),生效

--archive_state in()结果太多 走不了索引
CREATE INDEX oms_normal on sale_order_status(tenant_id,is_usable,is_paid,oms_process_type,is_invalidated,is_closed,last_update_time); CREATE INDEX oms_check on sale_order_status(tenant_id,is_usable,is_paid,oms_process_type,is_invalidated,is_closed,
is_checked,last_update_time); CREATE INDEX oms_suspend on sale_order_status(tenant_id,is_usable,is_paid,oms_process_type,is_invalidated,is_closed,
is_suspended,last_update_time); --sale_order
CREATE INDEX shop_idx on sale_order(shop_id,order_type);
CREATE INDEX platform_idx on sale_order(platform_order_status,order_type); --sale_order_warehouse
CREATE INDEX warehouse_idx on sale_order_warehouse(warehouse_id); --sale_order_courier
CREATE INDEX courier_idx on sale_order_courier(courier_id);

由于有新需求需要改造固定的查询sql(第三版)

@Service
public class OrderService extends TemplateService { private static final String isPaySql = " AND (is_paid = 1 OR pay_type = 4 ) ";
/**
* 订单处理:
* 过滤掉:合并拆分的订单
* 过滤掉:交易完成或交易关闭
* 要求:跑过预处理
* 要求:已付款或者货到付款
* 要求:未作废的
*/
public static final String DEFALUT_FILTER = " AND archive_state IN (0, 1) AND oms_process_type = 1 " +
isPaySql + " AND v_sale_order.is_invalidated=0 AND is_closed = 0";
/**
* 订单查询:
* 过滤掉:合并拆分的订单
*/
public static final String HISTORY_FILTER = " AND archive_state IN (0, 1)";
public static final String AFTER_FILTER = " AND archive_state IN (0,1,2) " + isPaySql;
}

改进:

1.将之前的is_paid 移除之前的索引

2.调整索引的顺序,移除毫无辨识度的字段

(第二版)

CREATE INDEX oms_normal_v2 on sale_order_status(tenant_id,is_closed,oms_process_type,is_invalidated,last_update_time);

CREATE INDEX oms_check_v2 on sale_order_status(tenant_id,is_closed,oms_process_type,is_invalidated,is_checked,last_update_time);

CREATE INDEX oms_suspend_v2 on sale_order_status(tenant_id,is_closed,oms_process_type,is_invalidated,is_suspended,last_update_time);

Q&A:

1.MySQL视图可以用索引吗?

我想答案是肯定的,其索引是建立在视图后面的真实表上,而不是建立在视图上.

索引是存放在模式(schema)中的一个数据库对象,索引的作用就是提高对表的检索查询速度,索引是通过快速访问的方法来进行快速定位数据,从而减少了对磁盘的读写操作。索引是数据库的一个对象,它不能独立存在,必须对某个表对象进行依赖。

视图就是一个表或多个表的查询结果,它是一张虚拟的表,因为它并不能存储数据。

mysql优化---订单查询优化(1):视图优化+索引创建的更多相关文章

  1. mysql优化---订单查询优化:视图优化+索引创建

    订单的表结构采用了垂直分表的策略,将订单相关的不同模块的字段维护在不同表中 在订单处理这个页面,需要查询各种维度, 因此为了方便查询创建了v_sale_order视图(老版本) drop view v ...

  2. MySQL的使用方法和视图、索引、以及存储过程的一些简单方法

    一,基本概念 1, 常用的两种引擎:         (1) InnoDB        a,支持ACID,简单地说就是支持事务完整性.一致性:         b,支持行锁,以及类似ORACLE的一 ...

  3. mysql优化---订单查询优化:异步分页处理

    订单分页查询: 老的代码是顺序执行查询数据和计算总记录数,但是如果条件复杂的话(比如关联子表)查询的时间要超过20s种 public static PagedList<Map<String ...

  4. mysql优化---订单查询优化(2):异步分页处理

    订单分页查询: 老的代码是顺序执行查询数据和计算总记录数,但是如果条件复杂的话(比如关联子表)查询的时间要超过20s种 public static PagedList<Map<String ...

  5. MySQL慢查询优化、索引优化、以及表等优化总结

    MySQL优化概述 MySQL数据库常见的两个瓶颈是:CPU和I/O的瓶颈. CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候. 磁盘I/O瓶颈发生在装入数据远大于内存容量的时候,如果应 ...

  6. 阿里P8架构师谈:MySQL慢查询优化、索引优化、以及表等优化总结

    更多内容:https://www.toutiao.com/i6599796228886626829/?tt_from=weixin&utm_campaign=client_share& ...

  7. mysql性能优化-慢查询分析、优化索引和配置

    一.优化概述 二.查询与索引优化分析 1性能瓶颈定位 Show命令 慢查询日志 explain分析查询 profiling分析查询 2索引及查询优化 三.配置优化 1)      max_connec ...

  8. 高性能MySql进化论(九):查询优化器常用的优化方式

    1        介绍 1.1     处理流程 当MYSQL 收到一条查询请求时,会首先通过关键字对SQL语句进行解析,生成一颗“解析树”,然后预处理器会校验“解析树”是否合法(主要校验数据列和表明 ...

  9. mysql优化:慢查询分析、索引配置优化

    一.优化概述二.查询与索引优化分析a.性能瓶颈定位show命令慢查询日志explain分析查询profiling分析查询b.索引及查询优化三.配置优化 max_connections back_log ...

随机推荐

  1. Codeforces 755E:PolandBall and White-Red graph(构造+思维)

    http://codeforces.com/contest/755/problem/E 题意:给出n个点和一个距离d,让你在这个n个点的图里面构造一个子图,使得这个子图的直径和补图的直径的较小值为d, ...

  2. 小白教程 Java web maven项目Windows下部署阿里云服务器全过程(买服务器,打包项目,连接服务器,配置服务器,部署项目)

    -------------首先:购买服务器---------------- Step1: 在https://www.aliyun.com/?utm_content=se_1043015注册登录阿里云 ...

  3. VS2010中GetMenu()和GetSubMenu(0)为NULL引发异常的解决方法 及添加方法

    对于前面问题的分析:来源于http://blog.163.com/yuyang_tech/blog/static/216050083201211144120401/ 解决方法1: //来源:http: ...

  4. js方法总结,不断更新...

    1. 返回<li> 元素父节点: document.getElementById("item1").parentNode; 2.   

  5. Excel催化剂开源第3波-修复ExcelCom加载项失效问题及WPS可调用Com加载项的方法

    为了还原一个干净无侵扰的网络世界,本文将不进行大规模地分发,若您觉得此文有用,不妨小范围地分享到真正有需要的人手中 功能概述 修复ExcelCom加载项常见问题,如每次需重新勾选COM加载项或COM加 ...

  6. 前端手势控制图片插件书写四(图片上传及Ios图片方向问题)

    1.在图片上传中,使用的input的type为File的属性.使用filereader的Api let that = this; var file = document.getElementById( ...

  7. Git的一些简单而且常用的操作

    转载自我自己的博客 介绍 很多初学者可能并不太清楚Git 与GitHub 这两个概念的联系和区别,在这里我大致介绍一下这两个名词. Git 是一个免费.开源的分布式版本控制系统(VCS).版本控制系统 ...

  8. Cesium 学习(一)环境搭建

    网上已有很多文章来教我们搭建Cesium的环境,我也没有必要再写一次:下面是我参照的文章的地址: 1.https://www.cnblogs.com/huqi-code/p/8287403.html  ...

  9. 今天来聊Java ClassLoader

    背景 类加载机制作为一个高频的面试题经常会在面试中被问到,前几天一个电话面试就问到,之前有了解过,但是没有梳理成自己的体系,所以说的有点凌乱,今天花点时间整理一下,分享给大家同时自己也好好梳理一下,顺 ...

  10. PHP对接口执行效率慢的优化

    PHP对接口执行效率慢的优化 PHP对接口执行效率慢的优化 造成执行效率低的原因可以由很多方面找原因 从代码层面,代码质量低,执行效率也会有很大影响的. 从硬件方面,服务器配置低,服务器配置是基础,这 ...