Индекс по запросу UNION? - PullRequest
       23

Индекс по запросу UNION?

2 голосов
/ 12 октября 2009

У меня есть запрос на объединение:

(SELECT INSTALLER, INSTALLTIME, RESULT, JOBNUMBER, HONAME, ADDRESS, CITY, STATE, ZIP, NOTES, SMNOTES, '' as priority, PAFS, upsell, TERM, MMRUPGRADE, WARRANTY, EFT FROM ACCOUNTS 
WHERE INSTALLDATE = '$date' && FUNDINGSTATUS !='DEAD') 
UNION 
(SELECT technician, servicetime, result, ID, Customername, address, city, state, zip, notes, board, priority, '', '', '', '', '', '' FROM service 
WHERE serviceday = '$date') 
ORDER BY INSTALLER, priority

Мне любопытно, поможет ли указание индекса в поле даты ускорить оба запроса? или тот факт, что я использую FUNDINGSTATUS в первом предложении where, заставит этот запрос не использовать индекс?

Ответы [ 3 ]

3 голосов
/ 12 октября 2009

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

Включите его с помощью

set profiling=1;

Чтобы просмотреть идентификатор запроса

show profiles;

И чтобы увидеть план выполнения:

show profile for query x;
2 голосов
/ 12 октября 2009

Отвечая на ваш вопрос:

Мне любопытно, поможет ли указание индекса в поле даты ускорить оба запроса?

Если условие для installdate и serviceday является селективным (то есть удовлетворяет несколько строк), тогда да, это поможет.

Поля даты обычно имеют тенденцию быть выборочными.

или тот факт, что я использую FUNDINGSTATUS в первом предложении where, заставит этот запрос не использовать индекс?

Да, индекс все еще будет использоваться.

Движок будет использовать индекс для выбора только записей с installdate = $date, а также будет дополнительно фильтровать значение fundingstatus.

Для достижения наилучших результатов создайте следующие индексы:

ACCOUNTS  (installdate, fundingstatus)
service (serviceday)

Если DEAD является частым значением для fundingstatus, может быть лучше переписать этот запрос следующим образом:

SELECT  INSTALLER, INSTALLTIME, RESULT, JOBNUMBER, HONAME, ADDRESS, CITY, STATE, ZIP, NOTES, SMNOTES, '' as priority, PAFS, upsell, TERM, MMRUPGRADE, WARRANTY, EFT
FROM    ACCOUNTS 
WHERE   INSTALLDATE = '$date' AND FUNDINGSTATUS < 'DEAD'
UNION ALL
SELECT  INSTALLER, INSTALLTIME, RESULT, JOBNUMBER, HONAME, ADDRESS, CITY, STATE, ZIP, NOTES, SMNOTES, '' as priority, PAFS, upsell, TERM, MMRUPGRADE, WARRANTY, EFT
FROM    ACCOUNTS 
WHERE   INSTALLDATE = '$date' AND FUNDINGSTATUS > 'DEAD'
UNION
SELECT  technician, servicetime, result, ID, Customername, address, city, state, zip, notes, board, priority, '', '', '', '', '', ''
FROM    service 
WHERE   serviceday = '$date'
ORDER BY
        INSTALLER, priority

, чтобы можно было использовать доступ к диапазону в обоих полях (installdate, fundingstatus).

0 голосов
/ 12 октября 2009

Наличие индекса для любого поля в предложении where всегда может повысить производительность, как много, так и мало.

Чтобы ответить на ваш вопрос о том, будет ли использоваться индекс «date», несмотря на то, что в первом запросе «FUNDINGSTATUS» в предложении where есть 2 ответа:

  • Если в таблице НЕТ ДРУГИХ индексов, то наиболее точно будет использоваться индекс даты. Это связано с тем, что поиск записей с определенной датой по индексу для БД намного менее эффективен, чем поиск по всей таблице, даже если для этого нужно проверить FUNDINGSTATUS после поиска указанных записей.

  • Если в той же таблице есть другие индексы, то ответ «это зависит».

    Это в основном зависит от того, какой% данных будет данными, которые не были отмечены, против% данных за определенную дату.

    Оптимизатор обычно пытается выбрать индекс, который сразу выберет наименьшее количество столбцов - например, если в вашей таблице есть данные за 100 дней, и 1/2 из них - пустые строки, то будет выбран индекс даты, поскольку он дает вам 1% данных без сканирования таблицы против 50% данных.

...