There's the table.
CREATE TABLE `refdata` (
`id` VARCHAR(36) NOT NULL COLLATE 'utf8_unicode_ci',
`uid` INT NOT NULL,
`data` TEXT NOT NULL COLLATE 'utf8_unicode_ci',
`ref_akid` TEXT NOT NULL COLLATE 'utf8_unicode_ci',
`ref_version` VARCHAR(16) NOT NULL COLLATE 'utf8_unicode_ci',
`remote_addr` VARCHAR(32) NOT NULL COLLATE 'utf8_unicode_ci',
`fetched_at` TIMESTAMP NULL,
`created_at` TIMESTAMP NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `link_to_user` (`uid`) USING BTREE,
CONSTRAINT `link_to_user` FOREIGN KEY (`uid`) REFERENCES `selfdb`.`admin_users` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;
The id is an UUID and the data is take about 1Mb. So the table is about 1.3G with 1.3M rows. Here's the result.
mysql> SELECT COUNT(*) FROM refdata;
+----------+
| COUNT(*) |
+----------+
| 1381991 |
+----------+
1 row in set (1 min 9.49 sec)
mysql> SELECT COUNT(*) FROM refdata WHERE uid > 0;
+----------+
| COUNT(*) |
+----------+
| 1382097 |
+----------+
1 row in set (0.29 sec)
Why the previous query is much slower than the second query?
P.S. There an app running and insert data. Are there some reasons about the table lock?
Here are explains.
mysql> explain SELECT COUNT(*) FROM refdata;
+----+-------------+------------+------------+-------+---------------+--------------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+-------+---------------+--------------+---------+------+---------+----------+-------------+
| 1 | SIMPLE | refdata | NULL | index | NULL | link_to_user | 4 | NULL | 1387770 | 100.00 | Using index |
+----+-------------+------------+------------+-------+---------------+--------------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
mysql> explain SELECT COUNT(*) FROM refdata WHERE uid > 0;
+----+-------------+------------+------------+-------+---------------+---------------+---------+------+--------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+-------+---------------+---------------+---------+------+--------+----------+--------------------------+
| 1 | SIMPLE | refdata | NULL | range | link_to_user | link_to_user | 4 | NULL | 693885 | 100.00 | Using where; Using index |
+----+-------------+------------+------------+-------+---------------+---------------+---------+------+--------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> explain SELECT * FROM refdata;
+----+-------------+------------+------------+------+---------------+------+---------+------+---------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+---------+----------+-------+
| 1 | SIMPLE | refdata | NULL | ALL | NULL | NULL | NULL | NULL | 1387771 | 100.00 | NULL |
+----+-------------+------------+------------+------+---------------+------+---------+------+---------+----------+-------+
1 row in set, 1 warning (0.00 sec)
mysql> explain SELECT * FROM refdata WHERE uid > 0;
+----+-------------+------------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| 1 | SIMPLE | refdata | NULL | ALL | link_to_user | NULL | NULL | NULL | 1387774 | 50.00 | Using where |
+----+-------------+------------+------------+------+---------------+------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
That is the expected behavior for InnoDB tables.
InnoDB engine supports transactions.So when you perform COUNT(*), the table must be fully scanned to avoid counting rows that are not yet commited.
But when you specify a filtering condition with WHERE
only the filtered rows need to be counted and since UID
in your case is an indexed column that is much faster.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments