I'm trying to hack a FLOSS application called Phabricator / Phorge
Let's take this simple MySQL table storing some questions by ID and their status (open, closed, invalid etc.):
CREATE TABLE `ponder_question` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`status` varchar(32) NOT NULL,
PRIMARY KEY (`id`),
KEY `status` (`status`),
I want to order by a specific status first, then the others. So:
SELECT * FROM ponder_question
ORDER BY status='open' DESC
LIMIT 5
It works but consider this DESCRIBE. That query is apparently examining 5000 rows which is probably too much / it is doing a full table scan:
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | ponder_question | NULL | index | NULL | status | 130 | NULL | 5000 | 100.00 | Using index; Using filesort |
(Instead, if you EXPLAIN a simple ORDER BY status DESC LIMIT 5 it examines just 5 rows)
To reduce the number of examined rows and avoid that Using filesort I also tried a FORCE INDEX:
SELECT * FROM ponder_question
FORCE INDEX (status)
ORDER BY status='open' DESC
LIMIT 5
I tested in MySQL 5.7 and MariaDB 10.3. Anyway, my question is not version-specific.
I guess I need to avoid this approach.
I maybe need to change the schema to have a simpler ordering clause, but maybe not.
To be honest, the final goal is to ORDER BY status='open' DESC, id, so showing all open questions by creation, and then all closed questions by creation.
I think this approach is bad, but I was just trying to be nice with this application, without proposing a schema change. So feel free to tell me that my question is stupid:
Question: how do you implement an order by a value first, in a more efficient way?
Some related similar approaches that apparently do not describe this problem:
ORDER BY status='open' DESC). This sorting cannot use the index. Rather thanORDER BY status DESC LIMIT 5which can and use the index. If you want the index to be used (which makes no sense for a table with 5k rows) then create an index by needed expression or, if the version cannot, by virtual generated column. – Akina Feb 10 '23 at 11:53