提高此查询的效率:使用联接和子查询进行更新

时间:2019-05-22 14:35:48

标签: mysql

我有一个
的mysql数据库 -需要寄送给他人的包裹表(此处为16,000条记录), account_no,服务上的索引
-价格表(500,000条记录)-价格取决于:交货地区,客户价格率和服务类型(例如第二天等),索引 面积,价格,服务
-邮政编码(或邮政编码)的第一部分表,其区域为(3000) -客户帐户表,包含价格比率(1600),价格比率索引
该查询找到发送包裹所需的价格,并使用唯一ID更新该包裹的客户价格
16000个包裹记录的价格更新需要70秒才能发送每个包裹

UPDATE
   tbl_parcel AS t20, ( 
   SELECT 
      id, service, rate_group, area, 
      (
         SELECT
            rate 
         FROM
            tbl_rates_all t4 
         WHERE
            t4.service = t10.service 
            AND t4.area = t10.area 
            AND t4.rate_group = t10.rate_group 
      )
      AS price 
   FROM
      (
         SELECT
            id,
            t1.service,
            rate_group,
            area
         FROM
            tbl_parcel t1 
            JOIN
               tbl_account t2 
               ON t1.account_no = t2.account_no 
            JOIN
               tbl_pr_postcode t3 
               ON LEFT(full_pcode, locate(' ', full_pcode) - 1) = t3.postcode 
      ) t10 
) AS src 
   SET
      t20.customer_price = src.price 
   WHERE
      t20.id = src.id

花费70秒处理16000个包裹记录

最终正是这部分影响了效率

从             tbl_rates_all t4          哪里             t4.service = t10.service             AND t4.area = t10.area             AND t4.rate_group = t10.rate_group

我可以为每个费率使用单独的费率表,因为这是原始设计,因此变量将称为tbl_rates001,可能只有3000条记录,而没有500,000条记录。在mysql中执行此操作的问题是,在运行中动态创建表名时,如果不使用准备好的语句就不可能,因此我认为这种方法不好。遗憾的是,您无法使用用户变量来保存价格汇率编号,然后将其添加到表格汇率名称中。

我对数据库和查询还很陌生,所以如果有什么让您尖叫的东西会有所帮助,那么谢谢您的投入

致谢

按要求添加架构

CREATE TABLE `tbl_x_rate_all` (
`id` bigint(20) NOT NULL, 
`service` varchar(4) NOT NULL,
`chargetype` char(1) NOT NULL,
`area` smallint(6) NOT NULL,
`rate` float(7,2) NOT NULL,
`rate_group` smallint(6) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
ALTER TABLE `tbl_x_rate_all` ADD PRIMARY KEY (`id`), ADD KEY `rate_group` (`rate_group`), ADD KEY `area` (`area`), ADD KEY `service` (`service`),   
ADD KEY `chargetype` (`chargetype`);

2 个答案:

答案 0 :(得分:0)

@Rich-

什么都没有跳出来。通过构建一些临时表,在主查询之外处理SET并使用一些OUTER APPLY而不是嵌套查询,您可能能够获得一些改进。

如果您通常对mysql /数据库还比较陌生,则EXPLAIN函数在优化中可能非常有用

https://dev.mysql.com/doc/refman/5.5/en/using-explain.html

答案 1 :(得分:0)

假设idrate_grouparea来自t1内部的t10,那么您的查询速度较慢?以下版本的版本:

UPDATE
    tbl_parcel AS t20
INNER JOIN (
    SELECT
        t1.id,
        t4.rate as price
    FROM tbl_parcel t1
    JOIN tbl_account t2 ON t1.account_no = t2.account_no
    JOIN tbl_pr_postcode t3 ON LEFT(full_pcode, locate(' ', full_pcode) - 1) = t3.postcode
    LEFT JOIN tbl_rates_all t4 ON t1.service = t4.service AND t1.area = t4.area
        AND t1.rate_group = t4.rate_group
    ) src ON t20.id = src.id
SET
    t20.customer_price = src.price
WHERE
    t20.id = src.id

我猜您可能会进一步丢失子查询,而子查询往往很麻烦:

UPDATE
    tbl_parcel AS t20
INNER JOIN tbl_parcel t1 ON t20.id = t1.id
INNER JOIN tbl_account t2 ON t1.account_no = t2.account_no
INNER JOIN tbl_pr_postcode t3 ON LEFT(full_pcode, locate(' ', full_pcode) - 1) = t3.postcode
LEFT JOIN tbl_rates_all t4 ON t1.service = t4.service AND t1.area = t4.area
        AND t1.rate_group = t4.rate_group
SET
    t20.customer_price = t4.rate
WHERE
    t20.id = t1.id
    -- can also replace with
    -- TRUE
    -- or lose it altogether
;

如果您有理由相信联接是瓶颈,则可以尝试在t1t4的联接上添加索引:

create index tbl_rates_all_service_area_rate_group_index
    on tbl_rates_all (service, area, rate_group);

create index tbl_parcel_service_area_rate_group_index
    on tbl_parcel (service, area, rate_group);