Самый быстрый запрос MYSQL SELECT с помощью JOINS (присоединиться)

У меня возникли проблемы с показателями и производительностью моего запроса.
В настоящее время я делаю следующее:

SELECT
images.imageId,
path,
fileName,
alt,
description,
width,
height
FROM
images
LEFT JOIN imagesEn ON images.imageId=imagesEn.imageId

WHERE

images.adId = ?

AND images.imageStatus = 1
AND images.isPreview = 1
AND (images.isBanner = 0 OR images.isBanner IS NULL)

ORDER BY RAND() LIMIT 1;';

Это дает мне изображение, которое я хочу. Но я использую адаптивные элементы изображения, есть меньшие версии изображения.
Мои ограниченные знания sql заставили меня использовать другой запрос, например, так:

SELECT
images.imageId,
relativePathToImageFromImgFolder,
fileName,
altAttribute,
description,
width,
height
FROM
images
LEFT JOIN imagesEn ON images.imageId=imagesEn.imageId

WHERE

images.adId = ?

AND images.imageStatus = 1
AND images.isPreview = 0
AND images.isSmallerVersionOf = ?

ORDER by width DESC

Затем я заканчиваю двумя запросами и двумя массивами, которые дают мне основное изображение плюс все меньшие версии изображения для создания элемента моей картинки.
Объединение необходимо, потому что у меня есть несколько языков (imagesEn, imagesDe, imagesFr и т. Д.), Которые соединяют имя файла, атрибуты на данном языке.
Я только что установил одностолбцевые индексы, многостолбцовые индексы для меня новы, о которых я слышал впервые за сегодня: D.
Я показываю что-то вроде producte на странице продукта, и мое время генерации страницы составляет около 0,3 секунд (без обналичивания). Все остальные мои страницы имеют 0,0x секунды, что также является моей целью для этой страницы.
Плюс я делаю этот запрос внутри цикла

$query = 'SELECT name, id, url, whatever from products where productColor = "blue";';
foreach($arr as $r)
{
$str .= '<div>';
$str .= $r['name'] . ' ' . $r['whatever'];
$str .= self::createPictureElementFromId($r['id']);  //this calls the above queries to create the picture element with its main image and the child images (smaller versions for smaller screens)
$str .= '</div>';
}

return $str;

Надеюсь, описание достаточно точное;).
заранее спасибо

0

Решение

Попробуй с этим. Он объединяет два раза таблицу изображений (один для обычного изображения и второй для уменьшенной версии, если она существует), и два раза — таблицу ImageEn, которая должна иметь перевод описания и другие вещи.

Если вы ищете только одно изображение, ваше время БД не будет намного лучше.

Псевдоним таблиц в полях выбора должен быть неправильным, потому что я не знаю, где это каждое поле. Описание должно быть на imagesEn и imagesEn2

Это только одна меньшая версия изображения. Если у вас есть много небольших изображений, вы можете присоединиться к таблице изображений в три раза, но ИМХО, это должно быть чище, чем вы делаете это сейчас, в вашем коде с двумя вариантами выбора.

SELECT
i.imageId,
i.path,
i.fileName,
i.alt,
i.description,
i.width,
i.height,
i2.relativePathToImageFromImgFolder,
i2.fileName,
i2.altAttribute,
i2.description,
i2.width,
i2.height

FROM
images as i
LEFT JOIN imagesEn as iEn ON i.imageId=iEn.imageId
LEFT JOIN images as i2 on ((i2.isSmallerVersionOf = i.imageID) AND (i2.imageStatus = 1)  AND (i2.isPreview = 0))
LEFT JOIN imagesEn2 as IEn2 ON i2.imageId = iEn2.imageId

WHERE

i2.adId = ?

AND i.imageStatus = 1
AND i.isPreview = 1
AND (i.isBanner = 0 OR i.isBanner IS NULL)

ORDER BY RAND() LIMIT 1;
0

Другие решения

i.isBanner = 0 OR i.isBanner IS NULL — Выбери один. Это позволит вам избавиться от OR, который является убийцей производительности.

Тогда есть INDEX(adId, imageStatus, isPreview, isBanner) (в любом порядке). Это должно позволить фильтрации работать быстрее.

Пожалуйста предоставьте SHOW CREATE TABLE, так как я должен угадать некоторые из ваших типов данных и т. д.

Сделать ORDER BY RAND() LIMIT 1, неэффективно перемещаться вокруг всех столбцов, только чтобы выбрать один из них. Итак, вместо этого сделайте это:

SELECT i.imageId, i.path, ...
FROM ( SELECT imageId FROM images WHERE ...
ORDER BY RAND() LIMIT 1 ) AS x
JOIN images i  USING(imageId)

Но тогда вам нужно INDEX(adId, imageStatus, isPreview, isBanner, imageId) так что внутренний запрос может выполняться полностью в индексе.

«Меньшая версия» — пусть флаг скажет «это маленькое изображение» и включите его в WHERE и INDEX,

Язык URL — Добавить еще один JOIN чтобы получить языковой URL, который должен быть в другой стол. Эта таблица должна иметь PRIMARY KEY(imageId, lang),

0

По вопросам рекламы [email protected]