Оптимизировать MySQL запрос с использованием индексов - PullRequest
5 голосов
/ 25 декабря 2011

У меня проблема с этим запросом:

SELECT DISTINCT s.city, pc.start, pc.end 
FROM postal_codes pc LEFT JOIN suspects s ON (s.postalcode BETWEEN pc.start AND      pc.end) 
WHERE pc.user_id = "username" 
ORDER BY pc.start

Подозреваемая таблица содержит около 340 000 записей, есть индекс по почтовому индексу, у меня несколько пользователей, но этот отдельный запрос занимает около 0,5 с, когдаЯ запускаю этот SQL с объяснением, я получаю что-то вроде этого: http://my.jetscreenshot.com/7536/20111225-myhj-41kb.jpg - означают ли эти NULL, что запрос не использует индекс?Индекс является BTREE, поэтому я думаю, что он должен работать немного быстрее.

Не могли бы вы помочь мне с этим?Если требуется какая-либо другая информация, просто дайте мне знать.

Редактировать: у меня есть индексы для sustims.postalcode, postal_codes.start, postal_codes.end, postal_codes.user_id.

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

user_id | start | end

Чем у меня есть таблица подозреваемых, где у каждого подозреваемого есть адрес (который содержитпочтовый индекс), поэтому в этом запросе я пытаюсь получить диапазон почтовых индексов - начало и конец, а также название города в этом диапазоне.

Надеюсь, это поможет.

Ответы [ 6 ]

2 голосов
/ 25 декабря 2011

Каждый раз, когда используется левое соединение, все записи первой таблицы выбираются, а не выбираются на основе индекса.Я бы предложил использовать внутреннее соединение.Нечто подобное в запросе ниже.

select distinct 
  s.city, 
  pc.start, 
  pc.end 
from postal_codes pc, suspect s 
where 
  s.postalcode between (select pc1.start, pc1.end from postal_code pc1 where pc1.user_id = "username" ) 
  and pc.user_id = "username"
order by pc.start
0 голосов
/ 25 декабря 2011

Попробуйте ИНДЕКС СИЛЫ .

0 голосов
/ 25 декабря 2011

Я думаю, что вы можете реструктурировать свой запрос следующим образом:

SELECT DISTINCT s.city, pc1.start, pc1.end FROM 
(SELECT pc.start and pc.end from postal_codes pc where pc.user_id = "username") as pc1,    Suspect s
WHERE s.postalcode BETWEEN pc1.start, pc1.end ORDER BY pc1.start

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

0 голосов
/ 25 декабря 2011

Я должен сказать, что я немного озадачен вашим соглашением об именах таблиц, я ожидал бы, что в «подозрительной» таблице будет user_id, а не postal_code, но вы должны иметь свои причины.Если вы оставите этот запрос как есть, вы можете добавить индекс для postal_code (star, end), чтобы избежать полного сканирования таблицы.

0 голосов
/ 25 декабря 2011

Не уверен на 100%, но это может иметь значение:

Иногда MySQL не использует индекс, даже если он доступен. Одно из обстоятельств, при которых это происходит, - это когда оптимизатор оценивает, что использование индекса потребовало бы от MySQL доступа к очень большому проценту строк в таблице. (В этом случае сканирование таблицы, вероятно, будет намного быстрее, поскольку требует меньше запросов.) Однако, если такой запрос использует LIMIT для извлечения только некоторых строк, MySQL в любом случае использует индекс, потому что он может гораздо быстрее найти несколько строк для возврата в результате.

Так что попробуйте протестировать с LIMIT, и если он использует индекс, вы нашли причину.

0 голосов
/ 25 декабря 2011

Используется только один индекс, а не для полей, участвующих в объединении.Попробуйте создать индекс для начального и конечного полей или используйте> = и <= вместо BETWEEN </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...