2009-08-27 3 views
2

У меня есть 2 вопроса.Оптимизация запросов

Первое:

SELECT * FROM `table` WHERE col='xyz' LIMIT 100 
//Time Taken: 0.0047s 

Второе:

SELECT * FROM `table` WHERE col='xyz' ORDER BY Id DESC LIMIT 100 
//Time Taken: 1.8208s 

Второй занимает гораздо больше времени. Я знаю, почему это так, потому что сначала я должен выбрать всю таблицу, а затем выполнить упорядочение, тогда как первый запрос возвращает только первые 100 строк.

Есть ли способ ORDER BY другим способом, например, выбрать последние 100 строк и затем выполнить заказ? Или я делаю запрос неправильно, и его можно сделать быстрее?

Обратите внимание, что идентификатор является автоинкрементным, поэтому при выборе последних строк по-прежнему будут возвращены правильные данные при его заказе.

CREATE TABLE `table`(
    `Id` BIGINT NOT NULL AUTO_INCREMENT, 
    `dateReg` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 

    PRIMARY KEY (`Id`) 
) ENGINE=MyISAM 
+0

Было бы справедливо предположить, учитывая вы используете автоинкрементного на ваш идентификатор, вы можете просто выбрать последний 100 строк? – Dave

+0

^да, но как выбрать последние 100 строк –

+0

Отправьте результат EXPLAIN (http://dev.mysql.com/doc/refman/5.0/en/explain.html) для обоих запросов, что поможет. Кроме того, что такое «намного больше времени»? Сколько времени занимает каждый запрос? –

ответ

3

Для последовательных идентификаторов:

SELECT t.* 
    FROM TABLE t 
    JOIN (SELECT MAX(t.id) 'maxid' 
      FROM TABLE t) max ON t.id BETWEEN max.maxid-100 AND max.maxid 
WHERE t.col = 'xyz' 

Для непоследовательных идентификаторами:

SELECT a.* 
    FROM (SELECT t.*, 
       @rownum := @rownum+1 AS rownum 
      FROM TABLE t, (SELECT @rownum := 0) r 
     WHERE t.col = 'xyz') a, 
     (SELECT COUNT(t.*) 'max' 
      FROM TABLE t 
     WHERE t.col = 'xyz') m 
WHERE a.rownum BETWEEN m.max-100 AND m.max 
+0

Это, однако, не вернет те же результаты, что и исходный запрос. Если вам требуется определенное количество записей в определенном порядке, вам необходимо сначала применить заказ. Похоже, что оригинальный плакат не заботится об этом, но кто-то другой, читающий это позже, может не понимать, что проблема с этим решением, когда вам нужны первые сотни записей в том порядке, который вы запросили у них. – HLGEM

+0

Немного о проблеме: Моя база данных работает, поэтому я не могу ее проверить, пока не доберусь туда. Однако я опубликую результаты, как только я получу его .... @HLGEM Мне нужно заказать последние 100 строк. Для дизайна важно, чтобы я отображал последние 100 строк, которые выглядели в базе данных. –

+0

Это скорее академическое любопытство для меня. Я предпочитаю не использовать подзапросы, если мне это не нужно, но на mySQL нет альтернативы (или Postgres). –

0

В столбце Идентификатор должен быть установлен в качестве первичного ключа (или если у вас есть какой-то другой первичный ключ, вы должны поставить индекс на нем в любом случае). Это должно ускорить запрос достаточно.

+0

Он проиндексирован ...такая же проблема –

1

Создайте составной индекс на (col, id), если вы используете MyISAM для своего стола.

В InnoDBPRIMARY KEY неявно включен в таблицу в качестве указателя строки, поскольку таблицы InnoDB индексируются по дизайну.

В случае InnoDB, чтобы сделать составной индекс на (col, id) достаточно создать индекс на col и убедитесь, что id является PRIMARY KEY.

Этот указатель будет использован для фильтрации по col и по заказу от id.

Указатель представляет собой структуру B-Tree, поэтому он может перебирать ASC и DESC с той же эффективностью.

+0

Составной индекс может помочь, но нет способа просто выбрать последние 100 строк, а не первые 100 строк. –

+0

'@Shahmir Javaid': индекс может работать в обоих направлениях с одинаковой эффективностью. Просто попробуйте. – Quassnoi

+0

Я буду .. но займет некоторое время, так как мне нужно отремонтировать таблицу миллионов записей –

Смежные вопросы