Search code examples
mysqlsqlquery-optimization

Complex query can't pick index in MySQL (8.0.29)


I have indexed the where clause column still not sure why the query didn't pick it up. If anyone knows the reason and if there is any possibility please suggest some.

Query:

select 
  t.seq_no, 
  t.property_id, 
  ifnull(s.property_count, 0) property_count

from 
  (
    select 
      '1' seq_no, 
      '109363' property_id, 
      'Basecoworks' as property_name
  ) t 
  left outer join (
    select 
      s.seq_no, 
      s.property_id, 
      s.property_name, 
      count(s.property_id) property_count 
    from 
      s_fl s 
    where 
      s.created_at between '2022-09-17 00:00:00' 
      and '2022-10-17 10:31:21' 
    group by 
      s.seq_no, 
      s.property_id, 
      s.property_name
  ) s on s.seq_no = t.seq_no 
order by 
  t.seq_no;

Explain plan:

*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: <derived2>
   partitions: NULL
         type: system
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: NULL
*************************** 2. row ***************************
           id: 1
  select_type: PRIMARY
        table: <derived3>
   partitions: NULL
         type: ref
possible_keys: <auto_key0>
          key: <auto_key0>
      key_len: 4
          ref: const
         rows: 10
     filtered: 100.00
        Extra: Using where
*************************** 3. row ***************************
           id: 3
  select_type: DERIVED
        table: s
   partitions: NULL
         type: ALL
possible_keys: created_at
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 55988164
     filtered: 50.00
        Extra: Using where; Using temporary
*************************** 4. row ***************************
           id: 2
  select_type: DERIVED
        table: NULL
   partitions: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
     filtered: NULL
        Extra: No tables used

Table structure:

*************************** 1. row ***************************
       Table: app
Create Table: CREATE TABLE `s_fl` (
  `funnel_id` int DEFAULT NULL,
  `app_id` int DEFAULT NULL,
  `platform` int DEFAULT NULL,
  `app_version_id` int NOT NULL,
  `seq_no` int NOT NULL,
  `property_id` bigint DEFAULT NULL,
  `property_name` varchar(255) DEFAULT NULL,
  `property_type` varchar(50) DEFAULT NULL,
  `asi` bigint NOT NULL,
  `created_at` datetime NOT NULL,
  `capture_time_relative` decimal(15,4) DEFAULT NULL,
  `last_event_id` bigint DEFAULT NULL,
  `last_event_name` varchar(100) DEFAULT NULL,
  `last_message_id` bigint DEFAULT NULL,
  `last_message_name` varchar(100) DEFAULT NULL,
  `last_tag_id` bigint DEFAULT NULL,
  `last_tag_name` varchar(100) DEFAULT NULL,
  `is_crash` tinyint DEFAULT NULL,
  `is_anr` tinyint DEFAULT NULL,
  `is_ragetap` tinyint DEFAULT NULL,
  `last_error_type_id` bigint DEFAULT NULL,
  `last_error_type` varchar(100) DEFAULT NULL,
  `screen_id` bigint DEFAULT NULL,
  `screen_name` varchar(100) DEFAULT NULL,
  `last_screen_id` bigint DEFAULT NULL,
  `last_screen_name` varchar(100) DEFAULT NULL,
  `user_task_id` bigint DEFAULT NULL,
  `ue_id` bigint DEFAULT NULL,
  PRIMARY KEY (`asi`,`seq_no`,`created_at`,`app_version_id`),
  UNIQUE KEY `unique_asi_seq_no` (`asi`,`seq_no`),
  KEY `seq_no_date` (`seq_no`,`created_at`),
  KEY `last_ids` (`last_screen_id`,`last_event_id`),
  KEY `created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

It's taking a long time I don't know where to modify it to improve the performance. does this have any possible options to make it optimize?

Sample data

+--------+-------------+----------------+
| seq_no | property_id | property_count |
+--------+-------------+----------------+
| 1      | 14236       |       07452475 |
+--------+-------------+----------------+

s table explain plan

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: s
   partitions: NULL
         type: ALL
possible_keys: created_at
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 54389573
     filtered: 50.00
        Extra: Using where; Using temporary

Solution

  • PRIMARY KEY (`asi`,`seq_no`,`created_at`,`app_version_id`),
    UNIQUE KEY `unique_asi_seq_no` (`asi`,`seq_no`),
    ...
    INDEX(created_at)
    

    -->

    PRIMARY KEY (`asi`,`seq_no`),
    INDEX(created_at, seq_no, property_id, property_name)
    

    Turn this into a WHERE clause:

    SELECT  '1' seq_no, '109363' property_id, 'Basecoworks' as property_name
    

    Then have

    INDEX(seq_no, property_id, property_name, created_at)
    

    The GROUP BY has 3 columns, but then JOINs on only one of them. Does this mean that seq_no uniquely represents one property? If so, several other things are 'wrong'.

    If property_id is NOT NULL, then use COUNT(*) instead of count(s.property_id)