Я выполняю запрос be
SELECT packages.id, packages.title, subcat.id, packages.weight
FROM packages ,provider, packagestosubcat,
packagestocity, subcat, usertosubcat,
usertocity, usertoprovider
WHERE packages.endDate >'2011-03-11 06:00:00' AND
usertosubcat.userid = 1 AND
usertocity.userid = 1 AND
packages.providerid = provider.id AND
packages.id = packagestosubcat.packageid AND
packages.id = packagestocity.packageid AND
packagestosubcat.subcatid = subcat.id AND
usertosubcat.subcatid = packagestosubcat.subcatid AND
usertocity.cityid = packagestocity.cityid AND
(
provider.providertype = 'reg' OR
(
usertoprovider.userid = 1 AND
provider.providertype != 'reg' AND
usertoprovider.providerid = provider.ID
)
)
GROUP BY packages.title
ORDER BY subcat.id, packages.weight DESC
Когда я запускаю объяснение, кажется, все выглядит нормально, за исключением сканирования таблицы usertoprovider, которое, кажется, не использует ключи таблицы:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE usertocity ref user,city user 4 const 4 Using temporary; Using filesort
1 SIMPLE packagestocity ref city,packageid city 4 usertocity.cityid 419
1 SIMPLE packages eq_ref PRIMARY,enddate PRIMARY 4 packagestocity.packageid 1 Using where
1 SIMPLE provider eq_ref PRIMARY,providertype PRIMARY 4 packages.providerid 1 Using where
1 SIMPLE packagestosubcat ref subcatid,packageid packageid 4 packages.id 1 Using where
1 SIMPLE subcat eq_ref PRIMARY PRIMARY 4 packagestosubcat.subcatid 1
1 SIMPLE usertosubcat ref userid,subcatid subcatid 4 const 12 Using where
1 SIMPLE usertoprovider ALL userid,providerid NULL NULL NULL 3735 Using where
Как видно из приведенного выше запроса, само условие:
provider.providertype = 'reg' OR
(
usertoprovider.userid = 1 AND
provider.providertype != 'reg' AND
usertoprovider.providerid = provider.ID
)
Индексируются обе таблицы - провайдера и пользователя. У провайдера есть индексы для ProvridID и типа провайдера, в то время как у usertoprovider есть индексы для ИД пользователей и ИД поставщика
Количество ключей:
provider.id = 47, provider.type = 1, usertoprovider.userid = 1245, usertoprovider.providerid = 6
Так что совершенно очевидно, что индексы не используются.
Далее, чтобы проверить это, я пошел дальше и:
- Дублируется таблица usertoprovider
- Вставить в клонированную таблицу все значения провайдеров, которые имеют providertype = 'reg'
- Упростил условие до (usertoprovider.userid = 1 И usertoprovider.providerid = provider.ID)
Время выполнения запроса изменено с 8,1317 с. на 0,0387 с.
Тем не менее, значения провайдеров, которые имеют providertype = 'reg', действительны для всех пользователей, и я хотел бы избежать вставки этих значений в таблицу usertoprovider для всех пользователей, поскольку эти данные являются избыточными.
Может кто-нибудь объяснить, почему MySQL все еще выполняет полное сканирование и не использует ключи? Что можно сделать, чтобы этого избежать?