简体   繁体   中英

Mysql IN() vs UNION ALL performance

Can someone explain the difference in performance characteristics of the following two queries if any?

Query 1

SELECT id FROM users WHERE status IN(1, 6, 11, 13);

Query 2

(SELECT id FROM users WHERE status = 1)
UNION ALL
(SELECT id FROM users WHERE status = 6)
UNION ALL
(SELECT id FROM users WHERE status = 11)
UNION ALL
(SELECT id FROM users WHERE status = 13)

I am aware that Query #1 is far more legible to a human.

I am interested in a discussion about how their performance characteristics might be the same or different. You can assume that there is an index on users.status

In second query, you are querying your table separately. For each select it has to read a table. In first approach it has to read the table once.

With an index, performance won't be much different.

Without an index, each table read would have to be full table scan and difference in performances between those two approaches will be even bigger.

Thus, first query will be faster.

With an index, the two should be essentially equivalent from a performance perspective. The basic process when an index is available is an index lookup to get the matching rows and then fetching the data pages. The first does this four times within a single query unit. The second does four query units on one id.

Without an index, the first should be faster -- up to four times faster if the table needs to be read from disk each time. Or just incrementally faster if the table fits in available memory and the subsequent scans are using a warm data page cache.

The first one would be faster. You can see it with profiling:

mysql> SET profiling = 1;
mysql> select * from bigtable where id in (200, 900, 22000, 88888);
mysql> select * from bigtable where id =200
-> union all
-> select * from bigtable where id =900
-> union all
-> select * from bigtable where id =22000
-> union all
-> select * from bigtable where id =88888;
mysql> show profile for query 1;
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000046 |
| checking permissions | 0.000006 |
| Opening tables       | 0.000013 |
| init                 | 0.000024 |
| System lock          | 0.000008 |
| optimizing           | 0.000009 |
| statistics           | 0.000031 |
| preparing            | 0.000010 |
| executing            | 0.000003 |
| Sending data         | 0.000072 |
| end                  | 0.000004 |
| query end            | 0.000006 |
| closing tables       | 0.000006 |
| freeing items        | 0.000013 |
| cleaning up          | 0.000008 |
+----------------------+----------+
15 rows in set, 1 warning (0,00 sec)

mysql> show profile for query 2;
+----------------------+----------+                                                                                                                                 
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000054 |
| checking permissions | 0.000006 |
| checking permissions | 0.000002 |
| checking permissions | 0.000003 |
| checking permissions | 0.000004 |
| Opening tables       | 0.000112 |
| init                 | 0.000058 |
| System lock          | 0.000009 |
| optimizing           | 0.000008 |
| statistics           | 0.000032 |
| preparing            | 0.000009 |
| optimizing           | 0.000005 |
| statistics           | 0.000017 |
| preparing            | 0.000005 |
| optimizing           | 0.000005 |
| statistics           | 0.000014 |
| preparing            | 0.000005 |
| optimizing           | 0.000005 |
| statistics           | 0.000014 |
| preparing            | 0.000006 |
| executing            | 0.000003 |
| Sending data         | 0.000018 |
| executing            | 0.000003 |
| Sending data         | 0.000008 |
| executing            | 0.000003 |
| Sending data         | 0.000007 |
| executing            | 0.000003 |
| Sending data         | 0.000007 |
| end                  | 0.000004 |
| query end            | 0.000007 |
| removing tmp table   | 0.000009 |
| query end            | 0.000002 |
| closing tables       | 0.000008 |
| freeing items        | 0.000020 |
| cleaning up          | 0.000011 |
+----------------------+----------+
35 rows in set, 1 warning (0,00 sec)

So the overhead of the separate queries inside union is there even if the actual execution is fast as the queries use index.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM