2014-07-16 2 views
0

Итак, рассмотрим некоторые запросы для Concrete5 и попытаемся сделать некоторые индексирования на своих таблицах. Я наткнулся на один запрос, который я подумал: «Там должен быть лучший способ», но мои исследования никуда не привели. Говоря конкретно, мой вопрос заключается в следующем: «Возможно ли написать раздел« if(p2.cID IS NULL, p1.cID, p2.cID) внутреннего соединения ». Я должен полагать, что это приводит к некоторой неэффективности для объединений, я приложил запрос к объяснению вывода в надежде, что кто-то еще скажет мне, действительно ли это имеет значение. Прямо сейчас это новая установка, поэтому не так много данных, но использование функции во внутреннем соединении просто кажется ... мне странно.MySQL Присоединиться к функции? Можно ли это улучшить?

Join of Ifs Explain

И запрос:

select p1.cID, pt.ptHandle, c.cDateAdded, pagepaths.cPath 
from Pages p1 left join Pages p2 on (p1.cPointerID = p2.cID) 
left join PagePaths on (PagePaths.cID = p1.cID and PagePaths.ppIsCanonical = 1) 
left join PageSearchIndex psi on (psi.cID = if(p2.cID is null, p1.cID, p2.cID)) 
inner join CollectionVersions cv on (cv.cID = if(p2.cID is null, p1.cID, p2.cID) and cvID = 1) 
left join PageTypes pt on (pt.ptID = if(p2.cID is null, p1.ptID, p2.ptID)) 
inner join Collections c on (c.cID = if(p2.cID is null, p1.cID, p2.cID)); 

запрос Время выполнения для запроса If без кэширования: 0,00161268

Обратите внимание все стыки, которые используют, если функцию. Я смог получить те же результаты запроса через запрос объединения, но я честно не уверен, что это более эффективно. Также имейте в виду, что с использованием PHP предложение where динамически добавляется, но я сейчас меньше беспокоюсь об этом. Я был бы открыт для предложений о том, как это можно улучшить, или если большинство людей скажут, что это будет масштабироваться просто отлично.

UPDATE

Здесь не Союз запросов (что значительно медленнее, с небольшим набором результатов работает) и Объясняю:

Union Query Explain

select p1.cID, pt.ptHandle, c.cDateAdded, pagepaths.cPath 
from Pages p1 left join Pages p2 on (p1.cPointerID = p2.cID) 
left join PagePaths on (PagePaths.cID = p1.cID and PagePaths.ppIsCanonical = 1) 
left join PageSearchIndex psi on (psi.cID = p1.cID AND p2.cID is null) 
inner join CollectionVersions cv on (cv.cID = p1.cID AND p2.cID is null and cvID = 1) 
left join PageTypes pt on (pt.ptID = p1.ptID AND p2.cID is null) 
inner join Collections c on (c.cID = p1.cID AND p2.cID is null) 
UNION 
select p1.cID, pt.ptHandle, c.cDateAdded, pagepaths.cPath 
from Pages p1 left join Pages p2 on (p1.cPointerID = p2.cID) 
left join PagePaths on (PagePaths.cID = p1.cID and PagePaths.ppIsCanonical = 1) 
left join PageSearchIndex psi on (psi.cID = p2.cID AND p2.cID is not null) 
inner join CollectionVersions cv on (cv.cID = p2.cID AND p2.cID is not null and cvID = 1) 
left join PageTypes pt on (pt.ptID = p2.ptID AND p2.cID is not null) 
inner join Collections c on (c.cID = p2.cID AND p2.cID is not null); 

запросов время исполнения для Союза запроса без кэш: 0,00763072

ОБНОВЛЕНИЕ 2 (Barm ar's Subquery Version)

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

Subquery Explain

Запрос:

SELECT p.cID, pt.ptHandle, c.cDateAdded, pp.cPath 
FROM (SELECT IFNULL(p2.cID, p1.cID) as cID, IFNULL(p2.ptID, p1.ptID) AS ptID 
     FROM Pages AS p1 
     LEFT JOIN Pages AS p2 ON (p1.cPointerID = p2.cID)) AS p 
left join PagePaths pp on (pp.cID = p.cID AND pp.ppIsCanonical = 1) 
left join PageSearchIndex psi on (psi.cID = p.cID) 
inner join CollectionVersions cv on (cv.cID = p.cID and cvID = 1) 
left join PageTypes pt on (pt.ptID = p.ptID) 
inner join Collections c on (c.cID = p.cID); 

запрос Время выполнения для подзапрос версии, без кэш-памяти: 0,00190587

+0

UNION может быть лучше. Другим вариантом является объединение с подзапросом, который возвращает 'p1.cID, p1.ptID' или' p2.cID, p2.ptID' в зависимости от 'p2.cID'. – Barmar

+0

Запрос на объединение, похоже, не идет, см. Обновленный вопрос –

+0

Есть ли конкретная причина использовать IF (... IS NULL, ...) вместо ISNULL или еще лучше, COALESCE, например 'on (psi.cID = COALESCE (p2.cID, p1.cID))?? –

ответ

1

Вот версия, которая соединяется с подзапроса, который возвращает соответствующие идентификаторы:

SELECT p.cID, p2.ptHandle, c.cDateAdded, pp.cPath 
FROM (SELECT IFNULL(p2.cID, p1.cID) as cID, IFNULL(p2.ptID, p1.ptID) AS ptID 
     FROM Pages AS p1 
     LEFT JOIN Pages AS p2 ON (p1.cPointerID = p2.cID)) AS p 
left join PagePaths pp on (PagePaths.cID = p.cID AND pp.ppIsCanonical = 1) 
left join PageSearchIndex psi on (psi.cID = p.cID) 
inner join CollectionVersions cv on (cv.cID = p.cID and cvID = 1) 
left join PageTypes pt on (pt.ptID = p.ptID) 
inner join Collections c on (c.cID = p.cID); 
+0

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

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