• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

mysql优化-订单查询优化:视图优化+目录创建_mysql

mysql 搞代码 7年前 (2018-06-09) 117次浏览 已收录 0个评论

mysql优化—订单查询优化:视图优化+索引创建

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

mysql优化-订单查询优化:视图优化+目录创建_mysql

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

mysql优化-订单查询优化:视图优化+目录创建_mysql

因此为了方便查询创建了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);

欢迎大家阅读《mysql优化-订单查询优化:视图优化+目录创建_mysql》,跪求各位点评,by 搞代码


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:mysql优化-订单查询优化:视图优化+目录创建_mysql

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址