January 28, 2021

MySQL count VS sum

Небольшое сравнение двух способов посчитать кол-во записей.

Табличка:

mysql> show create table mobile_stat_device\G
*************************** 1. row ***************************
       Table: mobile_stat_device
Create Table: CREATE TABLE `mobile_stat_device` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `deviceUuid` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Unique device ID',
  `deviceUuidHash` int unsigned GENERATED ALWAYS AS (crc32(`deviceUuid`)) STORED NOT NULL,
  `createdAt` datetime NOT NULL COMMENT 'Inserting date',
  PRIMARY KEY (`id`),
  UNIQUE KEY `deviceUuid_udx` (`deviceUuidHash`,`deviceUuid`),
  KEY `deviceUuidHash_idx` (`deviceUuidHash`)
) ENGINE=InnoDB AUTO_INCREMENT=2490316 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
1 row in set (0.00 sec)

Старый добрый count:

mysql> select count(1) from mobile_stat_device\G
*************************** 1. row ***************************
count(1): 2097152
1 row in set (2.20 sec)

Старый добрый sum:

mysql> select sum(1) from mobile_stat_device\G
*************************** 1. row ***************************
sum(1): 2097152
1 row in set (0.97 sec)

SUM быстрее COUNT более чем в два раза.

При том, что планы выполнения совпадают до буквы.

mysql> explain format=json select count(1) from mobile_stat_device\G
*************************** 1. row ***************************
EXPLAIN: {
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "213393.07"
    },
    "table": {
      "table_name": "mobile_stat_device",
      "access_type": "index",
      "key": "deviceUuidHash_idx",
      "used_key_parts": [
        "deviceUuidHash"
      ],
      "key_length": "4",
      "rows_examined_per_scan": 2088550,
      "rows_produced_per_join": 2088550,
      "filtered": "100.00",
      "using_index": true,
      "cost_info": {
        "read_cost": "4538.07",
        "eval_cost": "208855.00",
        "prefix_cost": "213393.07",
        "data_read_per_join": "318M"
      }
    }
  }
}
1 row in set, 1 warning (0.00 sec)
mysql> explain format=json select sum(1) from mobile_stat_device\G
*************************** 1. row ***************************
EXPLAIN: {
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "213393.07"
    },
    "table": {
      "table_name": "mobile_stat_device",
      "access_type": "index",
      "key": "deviceUuidHash_idx",
      "used_key_parts": [
        "deviceUuidHash"
      ],
      "key_length": "4",
      "rows_examined_per_scan": 2088550,
      "rows_produced_per_join": 2088550,
      "filtered": "100.00",
      "using_index": true,
      "cost_info": {
        "read_cost": "4538.07",
        "eval_cost": "208855.00",
        "prefix_cost": "213393.07",
        "data_read_per_join": "318M"
      }
    }
  }
}
1 row in set, 1 warning (0.00 sec)