Ответ 1
Ваш индекс сортируется по убыванию, поэтому, когда вы запрашиваете восхождение, ему нужно сделать гораздо больше работы, чтобы вернуть его в этом порядке.
Я полностью в тупике. По какой-то причине, когда я сортирую этот запрос по DESC, это очень быстро, но если отсортировано по ASC, это очень медленно.
Это займет около 150 миллисекунд:
SELECT posts.id
FROM posts USE INDEX (published)
WHERE posts.feed_id IN ( 4953,622,1,1852,4952,76,623,624,10 )
ORDER BY posts.published DESC
LIMIT 0, 50;
Это занимает около 32 секунд:
SELECT posts.id
FROM posts USE INDEX (published)
WHERE posts.feed_id IN ( 4953,622,1,1852,4952,76,623,624,10 )
ORDER BY posts.published ASC
LIMIT 0, 50;
EXPLAIN одинаково для обоих запросов.
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE posts index NULL published 5 NULL 50 Using where
Я отследил его до "USE INDEX (опубликовано)". Если я возьму это, то это будет одинаково для обоих способов. Но EXPLAIN показывает, что запрос менее эффективен в целом.
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE posts range feed_id feed_id 4 \N 759 Using where; Using filesort
И вот таблица.
CREATE TABLE `posts` (
`id` int(20) NOT NULL AUTO_INCREMENT,
`feed_id` int(11) NOT NULL,
`post_url` varchar(255) NOT NULL,
`title` varchar(255) NOT NULL,
`content` blob,
`author` varchar(255) DEFAULT NULL,
`published` int(12) DEFAULT NULL,
`updated` datetime NOT NULL,
`created` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `post_url` (`post_url`,`feed_id`),
KEY `feed_id` (`feed_id`),
KEY `published` (`published`)
) ENGINE=InnoDB AUTO_INCREMENT=196530 DEFAULT CHARSET=latin1;
Есть ли исправление для этого? Спасибо!
Ваш индекс сортируется по убыванию, поэтому, когда вы запрашиваете восхождение, ему нужно сделать гораздо больше работы, чтобы вернуть его в этом порядке.
Сначала вы можете получить свой набор данных, а затем заказать его.
Что-то вроде
SELECT posts.id FROM (
SELECT posts.id
FROM posts USE INDEX (published)
WHERE posts.feed_id IN ( 4953,622,1,1852,4952,76,623,624,10 )
LIMIT 0, 50
)
order by postS.id ASC;
Сначала он должен использовать индекс, чтобы найти все записи, которые удовлетворяют вашему запросу "where", и прикажет их заказать. Но порядок будет выполнен в меньшем наборе. Попробуйте, а затем сообщите нам.
С наилучшими пожеланиями.
Я бы не предложил вам создать другой индекс в таблице; каждый раз, когда строка вставлена или удалена, каждый индекс в таблице необходимо обновить, замедляя INSERT
запросы.
Индекс определенно замедляет его. Возможно, вы могли бы попробовать IGNORE
-вставить его:
SELECT posts.id
FROM posts IGNORE INDEX (published)
WHERE posts.feed_id IN ( 4953,622,1,1852,4952,76,623,624,10 )
ORDER BY posts.published ASC
LIMIT 0, 50;
Или, поскольку поле уже KEY
ed, вы можете попробовать следующее:
SELECT posts.id
FROM posts USE KEY (published)
WHERE posts.feed_id IN ( 4953,622,1,1852,4952,76,623,624,10 )
ORDER BY posts.published ASC
LIMIT 0, 50;
Как насчет того, чтобы перевернуть условие WHERE?
SELECT posts.id
FROM posts USE INDEX (published)
WHERE posts.feed_id IN ( 10,624,623,76,4952,1852,622,4953 )
ORDER BY posts.published DESC;
Вы хотите добавить индекс через (feed_id, опубликовано):
ALTER TABLE posts ADD INDEX (feed_id, published)
Это сделает этот запрос наилучшим, и вам не нужно будет форсировать определенный индекс с помощью USE INDEX.