mysql简单的分页查询为啥很慢很慢?请教大佬们有没有优化的方式?

67 阅读4分钟

问题描述: 有三张表:分别为投资人表、产品表、投资事件表,其中投资事件表中的唯一索引为:投资人id、产品id、融资的时间、融资轮次构成。具体表机构如下: 投资人表:

CREATE TABLE `f_investor` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '投资机构ID',
  `investor_name` varchar(255) DEFAULT NULL COMMENT '投资机构',
  `parent_company` varchar(255) DEFAULT NULL COMMENT '所属公司',
  `usc_code` varchar(255) DEFAULT NULL COMMENT '统一社会信用代码',
  `investor_type` varchar(255) DEFAULT NULL COMMENT '投资机构类型(国资)',
  `is_foreign_investment` varchar(255) DEFAULT NULL COMMENT '是否外资',
  `investor_region` varchar(255) DEFAULT NULL COMMENT '所属地区',
  `province` varchar(255) DEFAULT NULL COMMENT '省份',
  `tags` text COMMENT '机构标签,"|"分割',
  `introduction` longtext COMMENT '机构简介',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uk_investor_name` (`investor_name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='投资机构';

产品表:

CREATE TABLE `f_product` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '融资产品ID',
  `product_name` varchar(255) DEFAULT NULL COMMENT '融资产品',
  `product_introduction` text COMMENT '产品简介',
  `company_name` varchar(255) DEFAULT NULL COMMENT '公司名称',
  `usc_code` varchar(255) DEFAULT NULL COMMENT '统一社会信用代码',
  `company_introduction` text COMMENT '公司介绍',
  `area` varchar(255) DEFAULT NULL COMMENT '地区',
  `country` varchar(255) DEFAULT NULL COMMENT '国家',
  `province` varchar(255) DEFAULT NULL COMMENT '省份',
  `tags` text COMMENT '产品标签,"|"分割',
  `business_description` longtext COMMENT '业务描述',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uk_company_name` (`company_name`) USING BTREE,
  KEY `idx_province_city` (`province`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='融资产品';

事件表:

CREATE TABLE `f_event` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '融资事件ID',
  `product_id` int(11) DEFAULT NULL COMMENT '产品ID',
  `investor_id` int(11) DEFAULT NULL COMMENT '投资者id',
  `investor_name` varchar(255) DEFAULT NULL COMMENT '投资机构',
  `financing_round` varchar(255) DEFAULT NULL COMMENT '融资轮次',
  `financing_amount` varchar(255) DEFAULT NULL COMMENT '融资金额',
  `financing_amount_currency` varchar(255) DEFAULT NULL COMMENT '融资币种',
  `financing_amount_cny` decimal(20,4) DEFAULT NULL COMMENT '融资金额RMB(万)',
  `financing_amount_level` varchar(255) DEFAULT NULL COMMENT '融资金额量级',
  `release_date` varchar(20) DEFAULT NULL COMMENT '发布日期',
  `invest_dynamic` text COMMENT '投资动态',
  `invest_dynamic_url` text COMMENT '投资动态链接',
  `investment_phase` varchar(255) DEFAULT NULL COMMENT '投资阶段',
  `investment_amount` varchar(255) DEFAULT NULL COMMENT '投资金额(原始单位)',
  `investment_currency` varchar(255) DEFAULT NULL COMMENT '投资币种',
  `investment_amount_cny` decimal(20,4) DEFAULT NULL COMMENT '投资金额RMB(万)',
  `total_traded_equity` decimal(20,4) DEFAULT NULL COMMENT '总交易股权',
  `equity_percentage` decimal(20,4) DEFAULT NULL COMMENT '股权比例(投资方本次交易股权比例)',
  `investor_status` varchar(255) DEFAULT NULL COMMENT '投资方地位(投资方投资地位)',
  `post_money_valuation` varchar(255) DEFAULT NULL COMMENT '投后估值',
  `post_money_valuation_cny` decimal(20,4) DEFAULT NULL COMMENT '投后估值RMB',
  `pe_ratio` decimal(20,4) DEFAULT NULL COMMENT 'P/E',
  `transaction_status` varchar(255) DEFAULT NULL COMMENT '交易或发行状态',
  `transaction_type` varchar(255) DEFAULT NULL COMMENT '交易类型',
  `transaction_method` varchar(255) DEFAULT NULL COMMENT '交易方式',
  `related_party_transaction` varchar(10) DEFAULT NULL COMMENT '是否关联交易',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uk_investor_brand_stage` (`investor_id`,`product_id`,`financing_round`,`release_date`) USING BTREE,
  KEY `idx_product_id` (`product_id`) USING BTREE,
  KEY `idx_investor_id` (`investor_id`),
  KEY `idx_investment_amount_cny` (`investment_amount_cny`)
) ENGINE=InnoDB AUTO_INCREMENT=558322 DEFAULT CHARSET=utf8mb4 COMMENT='融资事件';

需求: 条件分页查询投资人列表,投资事件只显示投资人最新一条投资事件 查询条件有:投资人姓名模糊、融资轮次、融资时间、投资金额等等。 投资人表数据量:126013 产品表数据量:88281 投资事件表数量:515585

我的查询sql如下:

select t.investor_name, t.investor_region, t.province, t.parent_company, t2.release_date, t1.product_names, t2.financing_round, t2.invest_dynamic,
       t2.invest_dynamic_url,
       case when t2.investment_amount_cny is null then t2.investment_amount
            else concat(t2.investment_amount_cny, '万元') end investment_amount
from `apex_company`.f_investor t
       left join (
          select t.investor_id, t.release_date, GROUP_CONCAT(distinct t1.product_name) product_names, max(eventId) event_id
          from (
                select t.investor_id, t.release_date, t.product_id, t.id eventId
                from `apex_company`.f_event t,
                (
                  select max(release_date) release_date, investor_id
                  from `apex_company`.f_event
                  group by investor_id
                ) t1
                where t.investor_id = t1.investor_id and t.release_date = t1.release_date
                <if test="param.financingRound != null and param.financingRound != ''"> and t.financing_round = #{param.financingRound}</if>
                <if test="param.releaseBeginYear != null and param.releaseBeginYear != ''"> and t.release_date >= #{param.releaseBeginYear}</if>
                <if test="param.releaseEndYear != null and param.releaseEndYear != ''"> and t.release_date &lt;= #{param.releaseEndYear}</if>
                <if test="param.investmentAmountLevel != null and param.investmentAmountLevel != ''"> and t.investment_amount = '未披露'</if>
                <if test="param.investmentStartAmount != null and param.investmentStartAmount != ''"> and t.investment_amount_cny >= #{param.investmentStartAmount}</if>
                <if test="param.investmentEndAmount != null and param.investmentEndAmount != ''"> and t.investment_amount_cny &lt; #{param.investmentEndAmount}</if>
                <if test="param.investDynamic != null and param.investDynamic != ''"> and t.invest_dynamic like concat('%', #{param.investDynamic}, '%')</if>
              ) t
          left join `apex_company`.f_product t1 on t.product_id = t1.id
          <where>
            <if test="param.productName != null and param.productName != ''"> and t1.product_name like concat('%', #{param.productName}, '%')</if>
          </where>
          group by t.investor_id
        ) t1 on t.id = t1.investor_id
       left join `apex_company`.f_event t2 on t1.event_id = t2.id and t.id = t2.investor_id
where 1 = 1
  <if test="param.investorRegion != null and param.investorRegion != ''"> and t.investor_region = #{param.investorRegion}</if>
  <if test="param.province != null and param.province != ''"> and t.province = #{param.province}</if>
  <if test="param.financingRound != null and param.financingRound != ''"> and t2.financing_round = #{param.financingRound}</if>
  <if test="param.releaseBeginYear != null and param.releaseBeginYear != ''"> and t1.release_date >= #{param.releaseBeginYear}</if>
  <if test="param.releaseEndYear != null and param.releaseEndYear != ''"> and t1.release_date &lt;= #{param.releaseEndYear}</if>
  <if test="param.investmentAmountLevel != null and param.investmentAmountLevel != ''"> and t2.investment_amount = '未披露'</if>
  <if test="param.investmentStartAmount != null and param.investmentStartAmount != ''"> and t2.investment_amount_cny >= #{param.investmentStartAmount}</if>
  <if test="param.investmentEndAmount != null and param.investmentEndAmount != ''"> and t2.investment_amount_cny &lt; #{param.investmentEndAmount}</if>
  <if test="param.productName != null and param.productName != ''"> and t1.product_names like concat('%', #{param.productName}, '%')</if>
  <if test="param.investDynamic != null and param.investDynamic != ''"> and t.invest_dynamic like concat('%', #{param.investDynamic}, '%')</if>
  <if test="param.investorName != null and param.investorName != ''"> and t.investor_name like concat('%', #{param.investorName}, '%')</if>
order by t2.release_date desc, t.update_time desc

该如何优化才能更快呢?