如何优化连接查询?

How to optimize join query?

我最终使用的sql是这样的:

SELECT
    t1.account_id,
    t1.system_value,
    t1.date,
    acs.account_status
FROM
    (
    SELECT
        account.id,
        account.account_id,
        system_value,
        `date`
    FROM
        account,
        spend_daily_level
    WHERE
        account.id = spend_daily_level.`account_id`
        AND DATE BETWEEN '2021-12-01' AND '2021-12-23'
        AND account.`account_id` in (
        SELECT
            `market_accounts_`.`id` 
                   AS `account_id`
        FROM
            `market_accounts_`
        WHERE
            (`market_accounts_`.`ae` IN (112)
                AND `market_accounts_`.`medium` IN (0, 1, 2, 3, 18)))) t1
LEFT JOIN 
                   (
    SELECT
        account_id,
        SUBSTRING_INDEX(
                    GROUP_CONCAT(DISTINCT account_status ORDER BY date DESC), "," , 1) AS account_status
    FROM
        spend_daily_level
    GROUP BY
        account_id ) acs
                     ON
    t1.id = acs.account_id

下面是表格desc信息:

#  spend_daily_level

CREATE TABLE `spend_daily_level` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `active` tinyint(1) NOT NULL,
  `created_time` datetime(6) NOT NULL,
  `updated_time` datetime(6) NOT NULL,
  `date` date NOT NULL,
  `system_value` decimal(16,2) NOT NULL,
  `checked_value` decimal(16,2) NOT NULL,
  `account_id` int(11) NOT NULL COMMENT,
  `sale_leader_id` int(11) DEFAULT NULL ,
  `account_status` tinyint(3) DEFAULT,
  `growth` tinyint(1) NOT NULL DEFAULT,
  PRIMARY KEY (`id`),
  UNIQUE KEY `spend_daily_level_date_account_id_f38b1186_uniq` (`date`,`account_id`),
  KEY `spend_daily_level_account_id_f6df4f99_fk_account_id` (`account_id`),
  KEY `sale_leader_id` (`sale_leader_id`),
  KEY `date_active` (`active`,`date`),
  CONSTRAINT `spend_daily_level_ibfk_1` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`),
  CONSTRAINT `spend_daily_level_ibfk_2` FOREIGN KEY (`sale_leader_id`) REFERENCES `sale_leader` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24976133 DEFAULT CHARSET=utf8




# account

CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `active` tinyint(1) NOT NULL,
  `created_time` datetime(6) NOT NULL,
  `updated_time` datetime(6) NOT NULL,
  `account_id` varchar(45) NOT NULL,
  `is_pc` tinyint(1) DEFAULT NULL,
  `type` smallint(6) NOT NULL,
  `settlement_type` smallint(6) NOT NULL,
  `medium` smallint(6) NOT NULL,
  `ae_id` int(11) NOT NULL,
  `sale_id` int(11) DEFAULT NULL,
  `sign_id` int(11) NOT NULL,
  `sale_manage_id` int(11) DEFAULT NULL,
  `is_new_customer` tinyint(1) DEFAULT '0',
  `agency` tinyint(1) DEFAULT '0',
  `related_entity` varchar(255) DEFAULT NULL,
  `account_token_id` int(11) DEFAULT NULL,
  `entity_id` int(11) DEFAULT NULL,
  `merged_entity_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `account_account_id_medium_b46819c8_uniq` (`account_id`) USING BTREE,
  KEY `account_ae_id_4d0b721c_fk_auth_user_id` (`ae_id`),
  KEY `account_sale_id_7770cbad_fk_auth_user_id` (`sale_id`),
  KEY `account_sign_id_17d08191_fk_sign_id` (`sign_id`),
  KEY `sale_manage_id` (`sale_manage_id`),
  KEY `account_token_id` (`account_token_id`),
  KEY `entity_id` (`entity_id`),
  KEY `a_me_id` (`merged_entity_id`),
  CONSTRAINT `a_me_id` FOREIGN KEY (`merged_entity_id`) REFERENCES `merged_entity` (`id`),
  CONSTRAINT `account_ibfk_1` FOREIGN KEY (`ae_id`) REFERENCES `User` (`id`),
  CONSTRAINT `account_ibfk_2` FOREIGN KEY (`sale_id`) REFERENCES `User` (`id`),
  CONSTRAINT `account_ibfk_3` FOREIGN KEY (`sign_id`) REFERENCES `sign` (`id`),
  CONSTRAINT `account_ibfk_4` FOREIGN KEY (`sale_manage_id`) REFERENCES `sale` (`id`),
  CONSTRAINT `account_ibfk_5` FOREIGN KEY (`account_token_id`) REFERENCES `account_token` (`id`),
  CONSTRAINT `account_ibfk_6` FOREIGN KEY (`entity_id`) REFERENCES `entity` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=303393 DEFAULT CHARSET=utf8 


# market_accounts_

CREATE TABLE `market_accounts_` (
  `agency` int(11) DEFAULT NULL,
  `id` varchar(64) NOT NULL,
  `entity` varchar(255) DEFAULT NULL,
  `merged_entity` varchar(255) DEFAULT NULL,
  `related_entity` varchar(255) DEFAULT NULL,
  `type` tinyint(1) DEFAULT NULL,
  `our_side_entity` varchar(255) DEFAULT NULL,
  `short_title` varchar(255) DEFAULT NULL,
  `title` varchar(255) DEFAULT NULL COMMENT,
  `ae` int(11) DEFAULT NULL,
  `sale` int(11) DEFAULT NULL,
  `medium` tinyint(2) DEFAULT NULL,
  `is_pc` tinyint(1) DEFAULT NULL,
  `is_new_customer` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4



# explain 

id|select_type|table            |type  |possible_keys                                                                                      |key                                                |key_len|ref                                |rows    |Extra                |
--+-----------+-----------------+------+---------------------------------------------------------------------------------------------------+---------------------------------------------------+-------+-----------------------------------+--------+---------------------+
 1|PRIMARY    |<derived2>       |ALL   |                                                                                                   |                                                   |       |                                   |   23356|                     |
 1|PRIMARY    |<derived4>       |ref   |<auto_key0>                                                                                        |<auto_key0>                                        |4      |t1.id                              |     453|                     |
 4|DERIVED    |spend_daily_level|index |spend_daily_level_date_account_id_f38b1186_uniq,spend_daily_level_account_id_f6df4f99_fk_account_id|spend_daily_level_account_id_f6df4f99_fk_account_id|4      |                                   |10599162|                     |
 2|DERIVED    |spend_daily_level|range |spend_daily_level_date_account_id_f38b1186_uniq,spend_daily_level_account_id_f6df4f99_fk_account_id|spend_daily_level_date_account_id_f38b1186_uniq    |3      |                                   |   23356|Using index condition|
 2|DERIVED    |account          |eq_ref|PRIMARY                                                                                            |PRIMARY                                            |4      |bv_crm.spend_daily_level.account_id|       1|                     |
 2|DERIVED    |market_accounts_ |eq_ref|PRIMARY                                                                                            |PRIMARY                                            |258    |func                               |       1|Using where          |

现在 sql 执行起来很慢,我怎样才能加快它的速度?

非常感谢

SUBSTRING_INDEX(...) 看起来是执行“groupwise-max”的一种非常缓慢的方法。请找到更好的方法。看我添加的标签。

而且您可能不想要 LEFT

这些索引可能有帮助:

market_accounts_:  INDEX(ae, medium,  id)
spend_daily_level:  INDEX(account_id,  date)  -- in this order
spend_daily_level:  INDEX(account_id,  account_status)

并将其删除为多余的:spend_daily_level_account_id_f6df4f99_fk_account_id

请使用现代 JOIN 语法:

            FROM  account, spend_daily_level
            WHERE  account.id = spend_daily_level.`account_id`
              AND ...

==>

            FROM  account
            JOIN  spend_daily_level  ON  account.id = spend_daily_level.`account_id`
            WHERE ...

这里的不一致总有一天会咬你的:

  account:   `account_id` varchar(45) NOT NULL,
  market_accounts_:  `id` varchar(64) NOT NULL,