2

The table in question has millions of records. The following query is really slow (takes up to four minutes to perform), because MySQL picks the primary key as index.

SELECT 
 *
FROM
    `activities`
WHERE
`integration_id` = 11
ORDER BY `id` DESC
LIMIT 10 OFFSET 2

The table has multiple indexes, including an index on integration. When forced, the use of this index reduces the query time to about a second:

SELECT 
 *
FROM
    `activities`
USE INDEX (integration)
WHERE
`integration_id` = 11
ORDER BY `id` DESC
LIMIT 10 OFFSET 2

Using EXPLAIN, MySQL shows the following:

first query: (the slow one)

  • key: PRIMARY
  • key_len: 4
  • rows: 5472

second query: (the fast one)

  • key: integration
  • key_len: 5
  • rows: 24028

Seeing MySQL's explanation, I understand why it picks the primary key. However, in reality the amount of rows in the first query should be millions; and indeed is excruciatingly slow to execute.

Unfortunately I cannot just force the index in the query, because the query is dynamic (some other clauses can be included), and an ORM is used. So i'm looking for a solution in MySQL's configuration, if possible.

Extra info

I found altering the query in some cases resulted in MySQL picking the correct index. E.g. removing the ORDER BY clause, and replacing SELECT * with SELECT <insert every table column here>. I've no clue why. Removing the order is no option for me, and manually selecting every column is tricky with the ORM (apart from that, I would like to know why this fixes the index picking).

The EXPLAIN

  • id: '1'
  • select_type: 'SIMPLE'
  • table: 'activities'
  • type: 'index'
  • possible_keys: 'integration_category,integration_level,integration_category_level,integration'
  • key: PRIMARY
  • key_len: 4
  • ref: null
  • rows: '5473'
  • Extra Using where

SHOW CREATE TABLE

'CREATE TABLE `activities` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `content` text COLLATE utf8_unicode_ci NOT NULL,
  `parameters` text COLLATE utf8_unicode_ci,
  `input` text COLLATE utf8_unicode_ci,
  `output` text COLLATE utf8_unicode_ci,
  `response` text COLLATE utf8_unicode_ci,
  `integration_id` int(10) unsigned DEFAULT NULL,
  `level` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `category` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `integration_category` (`integration_id`,`category`),
  KEY `integration_level` (`integration_id`,`level`),
  KEY `integration_category_level` (`integration_id`,`category`,`level`),
  KEY `integration` (`integration_id`),
  CONSTRAINT `activities_integration_id_foreign` FOREIGN KEY (`integration_id`) REFERENCES `integrations` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=11262471 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci'
13
  • Add id DESC to your index... Commented Jul 12, 2017 at 8:53
  • @UsagiMiyamoto The question appears to be about MySQL, which AFAIK, silently ignores such parameters. Commented Jul 12, 2017 at 9:00
  • I've tried executing the query with ORDER BY 'id' ASC, to see if it would make any difference. It didn't. Commented Jul 12, 2017 at 9:01
  • Could you verify that id is your (single-column) primary key and that the index integration only consists of that one column? (Maybe add the create table for your table). Your 2nd query should not even take close to a second with correct indexes. And please add the complete explain output, especially the extra-part and information about partitions if you use them. You might also try an optimize table activities (although it should not have an effect here). Commented Jul 12, 2017 at 11:54
  • The table has 5 indexes in total: id (which is the single column primary key), integration (which is one column as well). This integration column is used in every query. Furthermore users can filter on two more columns, that's why three more indexes are used: integration_level, integration_category and integration_category_level. Since adding these indexes queries with these filters are very fast. The EXPLAIN: '1', 'SIMPLE', 'activities', 'index', 'integration_category,integration_level,integration_category_level,integration', 'PRIMARY', '4', NULL, '5473', 'Using where' Commented Jul 12, 2017 at 12:14

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.