Медленный MySQL порядок по столбцу даты и времени - PullRequest
1 голос
/ 21 февраля 2020

У меня есть таблица новостей, определенная следующим образом:

CREATE TABLE `news` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `creation_date` datetime DEFAULT NULL,
  `modification_date` datetime DEFAULT NULL,
  `active` bit(1) DEFAULT NULL,
  `mark_for_delete` bit(1) DEFAULT NULL,
  `verified` bit(1) DEFAULT NULL,
  `bot_id` int(11) DEFAULT NULL,
  `description` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `hash` varchar(100) NOT NULL,
  `published_at` datetime DEFAULT NULL,
  `source` varchar(255) DEFAULT NULL,
  `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `url` varchar(511) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_1dmji5m90xaiy84vttgkvsub2` (`hash`),
  KEY `index_news_source` (`source`),
  KEY `index_news_creation_date` (`creation_date`)
) ENGINE=InnoDB AUTO_INCREMENT=30887718 DEFAULT CHARSET=latin1

И таблица соединений для пометки новостей, принадлежащих некоторым популярным именам:

CREATE TABLE `star_news` (
  `stars_id` bigint(20) NOT NULL,
  `news_id` bigint(20) NOT NULL,
  PRIMARY KEY (`stars_id`,`news_id`),
  KEY `FK4eqjn8at6h4d9335q1plxkcnl` (`news_id`),
  CONSTRAINT `FK1olc51y8amp8op1kbmx269bac` FOREIGN KEY (`stars_id`) REFERENCES `star` (`id`),
  CONSTRAINT `FK4eqjn8at6h4d9335q1plxkcnl` FOREIGN KEY (`news_id`) REFERENCES `news` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Вот мой запрос, чтобы вернуть последнюю news

SELECT DISTINCT n.* 
FROM news n 
JOIN star_news sn 
  ON n.id = sn.news_id 
WHERE sn.stars_id IN (1234, 12345) 
ORDER BY n.creation_date DESC 
LIMIT 2;

Объясните:

+----+-------------+-------+------------+--------+-------------------------------------+---------+---------+-----------------------+------+----------+-----------------------------------------------------------+
| id | select_type | table | partitions | type   | possible_keys                       | key     | key_len | ref                   | rows | filtered | Extra                                                     |
+----+-------------+-------+------------+--------+-------------------------------------+---------+---------+-----------------------+------+----------+-----------------------------------------------------------+
|  1 | SIMPLE      | sn    | NULL       | range  | PRIMARY,FK4eqjn8at6h4d9335q1plxkcnl | PRIMARY | 8       | NULL                  |196225|   100.00 | Using where; Using index; Using temporary; Using filesort |
|  1 | SIMPLE      | n     | NULL       | eq_ref | PRIMARY                             | PRIMARY | 8       | cosmos_dev.sn.news_id |    1 |   100.00 | NULL                                                      |
+----+-------------+-------+------------+--------+-------------------------------------+---------+---------+-----------------------+------+----------+-----------------------------------------------------------+

Этот запрос занимает 20 секунд на моей машине. Если я уберу заказ по предложению, он вернется через миллисекунду. Как сделать заказ быстрее?

Я пытался использовать индекс силы на creation_date, так как это индексированный столбец, но это ухудшило производительность

Ответы [ 2 ]

0 голосов
/ 21 февраля 2020

Во-первых, напишите запрос как:

SELECT n.* 
FROM news n 
WHERE EXISTS (SELECT 1
              FROM star_news sn 
              WHERE n.id = sn.news_id AND
                    sn.stars_id IN (1234, 12345) 
             )
ORDER BY n.creation_date DESC
LIMIT 2 ;

Это исключит внешнее SELECT DISTINCT, которое должно помочь.

Затем создайте индекс для star_news(news_id, stars_id). Это также может использовать индекс на news(creation_date desc, id).

0 голосов
/ 21 февраля 2020

Итак, у вас есть 196 тыс. Новостных статей, относящихся к этим двум звездам? Дополнительная информация объясняет, что происходит:

Использование где; Использование индекса; Используя временные; Использование файловой сортировки

MySQL создает временный файл и сортирует его для удовлетворения заказа, поскольку он не может использовать индекс, который облегчил бы объединение и упорядочение статей по дате.

...