Оптимизация MySQL - WHERE и ORDER BY используют разные столбцы - PullRequest
3 голосов
/ 17 ноября 2011

У меня есть 115-мегабайтная таблица с 1 600 000 строк, в которой хранятся цены и координаты домов. «SELECT» запросы занимают слишком много времени. Мне было интересно, если кто-нибудь может предложить способ ускорить его.

Немного упрощенная версия моей таблицы ....

CREATE TABLE `prices1` (
    `price` INT(10) NOT NULL,
    `address` VARCHAR(127) NOT NULL,
    `lat` FLOAT(6,4) NOT NULL COMMENT 'GPS latitude',
    `lng` FLOAT(6,4) NOT NULL COMMENT 'GPS longitude',
    INDEX `lat` (`lat`),
    INDEX `price` (`price`)
) ENGINE=MyISAM ROW_FORMAT=DEFAULT

Этот запрос извлекает записи в пределах площади 2 мили х 2 мили ....

SELECT * FROM prices1
WHERE lat >= 55.9430 AND lat <= 55.9641
AND lng >= -3.2279 AND lng <= -3.1901                 
AND price >= 100000 and price <= 400000
ORDER BY price asc
LIMIT 50

... это занимает 0,8 секунды. EXPLAIN говорит, что использует индекс 'цена'.

Если я использую force index(lat), запрос выполняется за 0,1 секунды - намного быстрее, но мне бы очень хотелось, чтобы он еще быстрее.

Запрос будет выполняться через веб-сайт с несколькими пользователями. Все запросы будут одинаковыми, но с разными диапазонами для широты, долготы и цены. Скорость записи в таблицу не важна.

Кто-нибудь может подсказать, как я могу ускорить запрос? Или, по крайней мере, поощряйте MySQL использовать индекс 'lat', когда это лучший выбор (я бы не стал использовать 'force lat', так как я обнаружил, что запросы, извлекаемые из большей области, лучше выполнять с использованием индекса 'price').

Я запустил 'ANALYZE' и 'OPTOMIZE'.

Я прочитал в MySQL «порядок по индексации» - где один и тот же индекс может использоваться для предложений «WHERE» и «ORDER BY», но я не думаю, что его можно использовать там, где WHERE - диапазон?

Стоит ли искать «пространственные индексы»?

Любые идеи приветствуются, поскольку мне действительно нужно получить это намного быстрее.

1 Ответ

1 голос
/ 17 ноября 2011

Что произойдет, если вы сделаете:

INSERT INTO temporal
SELECT * FROM prices1
WHERE lat >= 55.9430 AND lat <= 55.9641
AND lng >= -3.2279 AND lng <= -3.1901                 
AND price >= 100000 and price <= 400000



SELECT * from temporal
ORDER BY price asc
LIMIT 50
...