我在索引和查询性能方面遇到了一些麻烦。 我目前正在做以下事情:
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 :(得分: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;
答案 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
中。
语言网址 - 向上方添加另一个JOIN
以获取特定于语言的网址,该网址应位于另一个表格中。该表格应为PRIMARY KEY(imageId, lang)
。