I have simplified a much larger table below:
CREATE TABLE `core` (
`id` int NOT NULL,
`loc_country` enum('United States','Colombia','United Kingdom',
'Australia','India','Germany','Canada','Korea','Netherlands',
'200 more') CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`loc_city` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_ci DEFAULT NULL,
`job` enum('a','b','c','d') CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `loc_country_2` (`loc_country`,`job`,`loc_city`(6))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
ROW_FORMAT=COMPRESSED
explain format=json
SELECT id FROM core
WHERE id!=518601449
AND loc_country='Mongolia'
AND id < 518601449
AND job='a'
LIMIT 151\G
*************************** 1. row ***************************
EXPLAIN: {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "14002.99"
},
"table": {
"table_name": "core",
"access_type": "range",
"possible_keys": [
"PRIMARY",
"loc_country_2"
],
"key": "loc_country_2",
"used_key_parts": [
"loc_country",
"job",
"loc_city",
"id"
],
"key_length": "34",
"rows_examined_per_scan": 45657,
"rows_produced_per_join": 45657,
"filtered": "100.00",
"using_index_for_skip_scan": true,
"cost_info": {
"read_cost": "9437.29",
"eval_cost": "4565.70",
"prefix_cost": "14002.99",
"data_read_per_join": "1G"
},
"used_columns": [
"id",
"loc_country",
"job"
],
"attached_condition": "((`api`.`core`.`job` = 'a') and (`api`.`core`.`loc_country` = 'Mongolia') and (`api`.`core`.`id` <> 518601449) and (`api`.`core`.`id` < 518601449))"
}
}
}
The query took 14 seconds to run, I need it to be done in 0.01 seconds
The biggest problem seems to be to use id < XXX and order by id, I thought that this should be "free" to use given that the id is primary key.
I need the id < and sort because I need to get a different portion out of the database with each query, if I'd not use it I would receive the same data with each query for each country+job
I can not parition the table as I have dozens of such queries using different columns, it's just one example.
I believe the compression makes a big impact, it might be responsible for most issues I have though I don't have the storage on my NVME disks to run without compression.
Would it help to add the primary key to the indexes I have? At the end ? I fear it would waste a lot of storage space.
Any ideas ?