mysql - 提高 MySQL 中存储过程的性能

标签 mysql loops stored-procedures database-performance insert-into

我正在尝试优化此存储过程。目前,当从链的最顶部完成此迭代时,可能需要大约 2.4-2.7 秒。如果可能的话,我希望将其降低到 1 秒以下。

我已经研究过如何优化它,并且 MySQL 自己的大多数技巧都不起作用。您不能在存储过程中LOCK 表或使用LOAD DATA 语句。运行测试时,INSERT INTO SELECT 语句似乎在此查询中花费了最多时间。

当我运行一次 CALL 时,我用了 2.6 秒的时间执行了大约 13 个 INSERT INTO 语句。至少有 3 个需要 0.43-0.45 秒才能完成。所有其他语句只需很少的时间即可完成。

这是我在“my.cnf”文件中的当前设置:

default-storage-engine = MyISAM
key_buffer_size = 256M
innodb_buffer_pool_size = 3G
innodb_buffer_pool_load_at_startup = ON
innodb_sort_buffer_size = 16M
innodb_flush_method = O_DIRECT
read_buffer_size = 4M
thread_stack = 256K
bulk_insert_buffer_size = 64MB

这是我的存储过程:

BEGIN
    DECLARE lastLayer INT;
    DECLARE lastInsertCount INT;
    DECLARE tempTableRowCount INT;
    DROP TABLE IF EXISTS `temp`;
    DROP TABLE IF EXISTS `pendingBusiness`;


    CREATE TABLE `temp`
    (
        `layer` INT(5),
        `title_c` VARCHAR(255), 
        `name` VARCHAR(255), 
        `rep_first_name` VARCHAR(255), 
        `rep_last_name` VARCHAR(255),
        `id_c` CHAR(36),
        `contact_status_reps_c` VARCHAR(255),
        `phone_mobile` VARCHAR(255),
        `contract_type_c` VARCHAR(255),
        `email_address` VARCHAR(255)
    );


    CREATE TABLE `pendingBusiness`
    (
        `layer` INT(5),
        `title_c` VARCHAR(255), 
        `name` VARCHAR(255), 
        `rep_first_name` VARCHAR(255), 
        `rep_last_name` VARCHAR(255),
        `id_c` CHAR(36),
        `contact_status_reps_c` VARCHAR(255),
        `investor_first_name` VARCHAR(255),
        `investor_last_name` VARCHAR(255),
        `product_detail` VARCHAR(255),
        `paperwork_status_c` VARCHAR(255),
        `next_step` VARCHAR(255),
        `outstanding_requirements_c` VARCHAR(255),
        `funding_status_c` VARCHAR(255),
        `funding_next_step_c` VARCHAR(255),
        `fulfillment_status_c` VARCHAR(255),
        `fulfillment_next_step_c` VARCHAR(255),
        `amount` VARCHAR(255),
        `stage` VARCHAR(255),
        `date_entered` DATETIME,
        `case_manager` VARCHAR(255),
        `lost_sale_date_c` DATETIME,
        `compensation_run_c` DATETIME,
        `product_id` CHAR(36),
        `rep_state` VARCHAR(255),
        `investor_state` VARCHAR(255)
    );

    INSERT INTO `temp`(`layer`, `title_c`, `name`, `rep_first_name`, `rep_last_name`, `id_c`, `contact_status_reps_c`, `phone_mobile`,`contract_type_c`,`email_address`)
    SELECT 0,
    wn_writing_number_cstm.title_c, 
    wn_writing_number.`name`, 
    preps_contracted_reps.first_name, 
    preps_contracted_reps.last_name, 
    wn_writing_number_cstm.id_c, 
    preps_contracted_reps_cstm.contact_status_reps_c, 
    preps_contracted_reps.phone_mobile, 
    preps_contracted_reps_cstm.contract_type_c, 
    email_addresses.email_address
FROM wn_writing_number LEFT OUTER JOIN wn_writing_number_cac_customize_agent_comp_1_c ON wn_writing_number_cac_customize_agent_comp_1_c.wn_writing946b_number_ida = wn_writing_number.id
     LEFT OUTER JOIN cac_customize_agent_comp ON wn_writing_number_cac_customize_agent_comp_1_c.wn_writing3148nt_comp_idb = cac_customize_agent_comp.id
     LEFT OUTER JOIN cac_customize_agent_comp_cstm ON cac_customize_agent_comp.id = cac_customize_agent_comp_cstm.id_c
     LEFT OUTER JOIN aos_products_cac_customize_agent_comp_1_c ON cac_customize_agent_comp_cstm.id_c = aos_products_cac_customize_agent_comp_1_c.aos_produca2b8nt_comp_idb
     LEFT OUTER JOIN preps_contracted_reps_wn_writing_number_1_c ON preps_contracted_reps_wn_writing_number_1_c.preps_contracted_reps_wn_writing_number_1wn_writing_number_idb = wn_writing_number.id
     LEFT OUTER JOIN preps_contracted_reps ON preps_contracted_reps_wn_writing_number_1_c.preps_cont9effed_reps_ida = preps_contracted_reps.id
     LEFT OUTER JOIN preps_contracted_reps_cstm ON preps_contracted_reps.id = preps_contracted_reps_cstm.id_c
     LEFT OUTER JOIN email_addr_bean_rel ON email_addr_bean_rel.bean_id = preps_contracted_reps_cstm.id_c
     LEFT OUTER JOIN email_addresses ON email_addr_bean_rel.email_address_id = email_addresses.id
     LEFT OUTER JOIN wn_writing_number_cstm ON wn_writing_number_cstm.id_c = wn_writing_number.id
    WHERE wn_writing_number_cstm.wn_writing_number_id_c = passId AND wn_writing_number.deleted = '0' AND preps_contracted_reps.deleted = '0' AND wn_writing_number.deleted = '0' AND email_addr_bean_rel.deleted = '0'
    GROUP BY wn_writing_number.`name`;

    INSERT INTO `pendingBusiness`(`title_c`, `name`, `rep_first_name`, `rep_last_name`, `id_c`, `contact_status_reps_c`, `investor_first_name`, `investor_last_name`, `product_detail`, `paperwork_status_c`, `next_step`, `outstanding_requirements_c`, `funding_status_c`, `funding_next_step_c`, `fulfillment_status_c`, `fulfillment_next_step_c`, `amount`, `stage`, `date_entered`, `case_manager`, `lost_sale_date_c`, `compensation_run_c`, `product_id`, `rep_state`, `investor_state`)
    SELECT
    wn_writing_number_cstm.title_c, 
    wn_writing_number.`name`,
    preps_contracted_reps.first_name, 
    preps_contracted_reps.last_name, 
    wn_writing_number_cstm.id_c, 
    preps_contracted_reps_cstm.contact_status_reps_c, 
    contacts.first_name, 
    contacts.last_name, 
    aos_products.`name`, 
    opportunities_cstm.paperwork_status_c, 
    opportunities.next_step, 
    opportunities_cstm.outstanding_requirements_c, 
    opportunities_cstm.funding_status_c, 
    opportunities_cstm.funding_next_step_c, 
    opportunities_cstm.fulfillment_status_c, 
    opportunities_cstm.fulfillment_next_step_c, 
    opportunities.amount,
    opportunities_cstm.stage_c,
    opportunities.date_entered,
    CONCAT(users.first_name, " ", users.last_name) AS case_manager,
    opportunities_cstm.lost_sale_date_c,
    opportunities_cstm.compensation_run_c,
    aos_products.id,
    preps_contracted_reps.primary_address_state,
    opportunities_cstm.state_of_residence_c
FROM wn_writing_number 
     LEFT OUTER JOIN preps_contracted_reps_wn_writing_number_1_c ON preps_contracted_reps_wn_writing_number_1_c.preps_contracted_reps_wn_writing_number_1wn_writing_number_idb = wn_writing_number.id
     LEFT OUTER JOIN preps_contracted_reps ON preps_contracted_reps_wn_writing_number_1_c.preps_cont9effed_reps_ida = preps_contracted_reps.id
     LEFT OUTER JOIN preps_contracted_reps_cstm ON preps_contracted_reps.id = preps_contracted_reps_cstm.id_c
     LEFT OUTER JOIN wn_writing_number_cstm ON wn_writing_number_cstm.id_c = wn_writing_number.id
     LEFT OUTER JOIN opportunities_cstm ON opportunities_cstm.wn_writing_number_id_c = wn_writing_number.id
     LEFT OUTER JOIN contacts ON opportunities_cstm.contact_id_c = contacts.id
     LEFT OUTER JOIN opportunities ON opportunities_cstm.id_c = opportunities.id
     LEFT OUTER JOIN aos_products ON opportunities_cstm.aos_products_id_c = aos_products.id
     LEFT OUTER JOIN users ON opportunities_cstm.user_id_c = users.id
WHERE wn_writing_number.id = passId AND opportunities.deleted = '0' AND opportunities.date_entered >= DATE_SUB(NOW(),INTERVAL 1.5 YEAR)
GROUP BY opportunities_cstm.id_c;

    SET lastLayer := 0;
    SET lastInsertCount := 1;

    LayerLoop: WHILE lastInsertCount > 0 DO
      INSERT INTO `temp`(`layer`, `title_c`, `name`, `rep_first_name`, `rep_last_name`, `id_c`, `contact_status_reps_c`, `phone_mobile`,`contract_type_c`,`email_address`)
      SELECT lastLayer + 1,
        wn_writing_number_cstm.title_c, 
        wn_writing_number.`name`, 
        preps_contracted_reps.first_name, 
        preps_contracted_reps.last_name, 
        wn_writing_number_cstm.id_c,
        preps_contracted_reps_cstm.contact_status_reps_c, 
        preps_contracted_reps.phone_mobile, 
        preps_contracted_reps_cstm.contract_type_c, 
        email_addresses.email_address
    FROM wn_writing_number LEFT OUTER JOIN wn_writing_number_cac_customize_agent_comp_1_c ON wn_writing_number_cac_customize_agent_comp_1_c.wn_writing946b_number_ida = wn_writing_number.id
         LEFT OUTER JOIN cac_customize_agent_comp ON wn_writing_number_cac_customize_agent_comp_1_c.wn_writing3148nt_comp_idb = cac_customize_agent_comp.id
         LEFT OUTER JOIN cac_customize_agent_comp_cstm ON cac_customize_agent_comp.id = cac_customize_agent_comp_cstm.id_c
         LEFT OUTER JOIN aos_products_cac_customize_agent_comp_1_c ON cac_customize_agent_comp_cstm.id_c = aos_products_cac_customize_agent_comp_1_c.aos_produca2b8nt_comp_idb
         LEFT OUTER JOIN preps_contracted_reps_wn_writing_number_1_c ON preps_contracted_reps_wn_writing_number_1_c.preps_contracted_reps_wn_writing_number_1wn_writing_number_idb = wn_writing_number.id
         LEFT OUTER JOIN preps_contracted_reps ON preps_contracted_reps_wn_writing_number_1_c.preps_cont9effed_reps_ida = preps_contracted_reps.id
         LEFT OUTER JOIN preps_contracted_reps_cstm ON preps_contracted_reps.id = preps_contracted_reps_cstm.id_c
         LEFT OUTER JOIN email_addr_bean_rel ON email_addr_bean_rel.bean_id = preps_contracted_reps_cstm.id_c
         LEFT OUTER JOIN email_addresses ON email_addr_bean_rel.email_address_id = email_addresses.id
         LEFT OUTER JOIN wn_writing_number_cstm ON wn_writing_number_cstm.id_c = wn_writing_number.id
      WHERE wn_writing_number_cstm.wn_writing_number_id_c IN (SELECT id_c FROM `temp` WHERE layer = lastLayer) AND wn_writing_number.deleted = '0' AND preps_contracted_reps.deleted = '0' AND wn_writing_number.deleted = '0' AND email_addr_bean_rel.deleted = '0'
      GROUP BY wn_writing_number.`name`;

      SET lastInsertCount := ROW_COUNT();

      INSERT INTO `pendingBusiness`(`layer`, `title_c`, `name`, `rep_first_name`, `rep_last_name`, `id_c`, `contact_status_reps_c`, `investor_first_name`, `investor_last_name`, `product_detail`, `paperwork_status_c`, `next_step`, `outstanding_requirements_c`, `funding_status_c`, `funding_next_step_c`, `fulfillment_status_c`, `fulfillment_next_step_c`, `amount`, `stage`, `date_entered`, `case_manager`, `lost_sale_date_c`, `compensation_run_c`, `product_id`, `rep_state`, `investor_state`)
      SELECT lastLayer + 1,
        wn_writing_number_cstm.title_c, 
        wn_writing_number.`name`, 
        preps_contracted_reps.first_name, 
        preps_contracted_reps.last_name, 
        wn_writing_number_cstm.id_c, 
        preps_contracted_reps_cstm.contact_status_reps_c, 
        contacts.first_name, 
        contacts.last_name, 
        aos_products.`name`, 
        opportunities_cstm.paperwork_status_c, 
        opportunities.next_step, 
        opportunities_cstm.outstanding_requirements_c, 
        opportunities_cstm.funding_status_c, 
        opportunities_cstm.funding_next_step_c, 
        opportunities_cstm.fulfillment_status_c, 
        opportunities_cstm.fulfillment_next_step_c, 
        opportunities.amount,
        opportunities_cstm.stage_c,
        opportunities.date_entered,
        CONCAT(users.first_name, " ", users.last_name) AS case_manager,
        opportunities_cstm.lost_sale_date_c,
        opportunities_cstm.compensation_run_c,
        aos_products.id,
        preps_contracted_reps.primary_address_state,
        opportunities_cstm.state_of_residence_c
    FROM wn_writing_number 
         LEFT OUTER JOIN preps_contracted_reps_wn_writing_number_1_c ON preps_contracted_reps_wn_writing_number_1_c.preps_contracted_reps_wn_writing_number_1wn_writing_number_idb = wn_writing_number.id
         LEFT OUTER JOIN preps_contracted_reps ON preps_contracted_reps_wn_writing_number_1_c.preps_cont9effed_reps_ida = preps_contracted_reps.id
         LEFT OUTER JOIN preps_contracted_reps_cstm ON preps_contracted_reps.id = preps_contracted_reps_cstm.id_c
         LEFT OUTER JOIN wn_writing_number_cstm ON wn_writing_number_cstm.id_c = wn_writing_number.id
         LEFT OUTER JOIN opportunities_cstm ON opportunities_cstm.wn_writing_number_id_c = wn_writing_number.id
         LEFT OUTER JOIN contacts ON opportunities_cstm.contact_id_c = contacts.id
         LEFT OUTER JOIN opportunities ON opportunities_cstm.id_c = opportunities.id
         LEFT OUTER JOIN aos_products ON opportunities_cstm.aos_products_id_c = aos_products.id
         LEFT OUTER JOIN users ON opportunities_cstm.user_id_c = users.id
      WHERE opportunities.deleted = '0' AND wn_writing_number_cstm.wn_writing_number_id_c IN (SELECT id_c FROM `temp` WHERE layer = lastLayer) AND opportunities.date_entered >= DATE_SUB(NOW(),INTERVAL 1.5 YEAR)
      GROUP BY opportunities_cstm.id_c;

      SET lastLayer := lastLayer + 1;
    END WHILE LayerLoop;


    SELECT `title_c`, `name`, `rep_first_name`, `rep_last_name`, `id_c`, `contact_status_reps_c`, `investor_first_name`, `investor_last_name`, `product_detail`, `paperwork_status_c`, `next_step`, `outstanding_requirements_c`, `funding_status_c`, `funding_next_step_c`, `fulfillment_status_c`, `fulfillment_next_step_c`, `amount`, `stage`, `date_entered`, `case_manager`, `lost_sale_date_c`, `compensation_run_c`, `product_id`, `rep_state`, `investor_state`
    FROM `pendingBusiness`
    ORDER BY rep_first_name ASC;

    DROP TABLE IF EXISTS `pendingBusiness`;
END

最佳答案

FWIW,您的查询在功能上与以下查询相同。然而,以下内容的优点是更容易阅读。也就是说,您的 GROUP BY 子句将为除 name 之外的所有内容返回(可能)不确定的结果。

SELECT 0
     , k.title_c
     , a.name
     , g.first_name
     , g.last_name
     , k.id_c
     , h.contact_status_reps_c
     , g.phone_mobile
     , h.contract_type_c
     , j.email_address
  FROM wn_writing_number a
  JOIN wn_writing_number_cac_customize_agent_comp_1_c b
    ON b.wn_writing946b_number_ida = a.id
  JOIN cac_customize_agent_comp c
    ON c.id = b.wn_writing3148nt_comp_idb 
  LEFT 
  JOIN cac_customize_agent_comp_cstm d 
    ON d.id_c = c.id 
  LEFT 
  JOIN aos_products_cac_customize_agent_comp_1_c e 
    ON e.aos_produca2b8nt_comp_idb = d.id_c 
  LEFT 
  JOIN preps_contracted_reps_wn_writing_number_1_c f
    ON f.preps_contracted_reps_wn_writing_number_1wn_writing_number_idb = a.id 
  JOIN preps_contracted_reps g
    ON g.id = f.preps_cont9effed_reps_ida
  LEFT 
  JOIN preps_contracted_reps_cstm h
    ON h.id_c = g.id  
  JOIN email_addr_bean_rel i
    ON i.bean_id = h.id_c
  LEFT 
  JOIN email_addresses j
    ON j.id = i.email_address_id  
  JOIN wn_writing_number_cstm k
    ON k.id_c = a.id
 WHERE k.wn_writing_number_id_c = passId 
   AND a.deleted = 0 
   AND g.deleted = 0 
   AND i.deleted = 0
 GROUP 
    BY a.name;

关于mysql - 提高 MySQL 中存储过程的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44399135/

相关文章:

php - 提取唯一订单

mysql - 使用 GROUP BY 语句的 SQL 查询

mysql - nodejs mysql查询仅显示一条记录而不是数据库中的所有记录

mysql - 尝试显示时 SQL 歧义

c# - 将动态长度的数组插入和更新到表中

sql-server - 带有可选参数的 SQL Server 存储过程更新了错误的列

sql-server - 是否可以在 SQL Server 2008 中使用存储过程作为子查询?

java - 限制每行的输出

c++ - while 循环、字符串和整数

algorithm - 在没有循环或 if 语句的情况下执行循环 x 次