如何使用特定搜索条件更好地优化MySQL SELECT语句?

时间:2019-01-11 17:27:43

标签: php mysql database

我开发了一种图像搜索工具,可以对所有图像的目录建立索引,存储数据,然后根据搜索结果。

这是可行的,但是由于数据量大(用于150,000张图像的约270万行元数据),返回结果花费了很长时间(有时> 5分钟)。我相信这是由于在foreach循环中查询第二组数据。我希望将sql合并为一条语句以更好地进行优化(除非有另一种方法!)。

到目前为止,我将返回所有元数据与搜索词匹配的image_id,然后使用返回的image_id获取每个图像的元数据表中的所有元数据。这是数据库的基本结构:

SELECT image_id
FROM metadata
WHERE (meta_value LIKE '%runner%')
AND meta_key IN ('keyword', 'filename', 'description')
GROUP BY image_id

1。

到目前为止,我的代码从获取搜索词“ runner”匹配的所有图片开始(因此图片1和3)

$search_results = $imagesearch->search_images(); //object array from above sql

foreach ($search_results as $image) {
    $id = $image->image_id;
    $get_metadata = $imageget->get_metadata($id)
}

2。

然后遍历返回的结果集并获取每个结果的元数据:

SELECT *
FROM metadata 
WHERE image_id = $id

3。

Array
(
    [1] => array(
        [image_id] => 1
        [filename] => image_XYZ.jpg
        [thumb] => image_XYZ_thumb.jpg
        [filetype] => jpg
        [keyword] => runner
        [height] => 600
    ),
    [2] => array(
        [image_id] => 3
        [filename] => runner_bean.jpg
        [thumb] => runner_bean_thumb.jpg
        [filetype] => jpg
        [filesize] => 12485
        [description] => runnerbean
        [keyword] => runner
        [keyword] => vegetable
    ),
)

然后使用元数据提取meta_key等于我想要的数据(例如height)以检索值等的行。

所以我的最终数组看起来像这样:

SELECT *
FROM metadata m
LEFT JOIN image i ON i.image_id = m.image_id
WHERE i.image_id IN (
    SELECT image_id
    FROM metadata
    WHERE $search
    AND meta_key IN ('keyword', 'filename', 'description')
    GROUP BY image_id
)
GROUP BY m.image_id

到目前为止,我的工作是使用子查询首先获取与搜索字词匹配的图片,然后获取这些图片的元数据:

{{1}}

我的分组依据是按图像ID折叠结果,因此我仅获得每个图像的第一行(上述示例中的文件类型)。是否有一种方法可以获取与搜索词匹配的最终图像数组,并以更优化的方式返回每个图像的元数据?

任何帮助将不胜感激

1 个答案:

答案 0 :(得分:0)

我看不到查询中第二个GROUP BY的含义,我想您需要删除它。然后,查询将为每个图像元数据生成一行,并按图像排序。这并不完全是您期望的结构(这需要旋转结果集),但是您可以遍历它并动态生成数组数组(每次image_id更改时,就开始提供新的子数组)在您的全局数组中。)

SELECT m.*
FROM metadata m
WHERE m.image_id IN (
    SELECT DISTINCT image_id
    FROM metadata
    WHERE 
        meta_value LIKE '%runner%'
        AND meta_key IN ('keyword', 'filename', 'description')
)
ORDER BY m.image_id

注意:根据数据的外观,内部查询中的SELECT DISTINCT可能比SELECT更为有效。

另一个选项(产生相同的结果集)是使用带有WHERE EXISTS子句的相关子查询,如下所示:

SELECT m.*
FROM metadata m
WHERE EXISTS (
    SELECT 1
    FROM metadata
    WHERE 
        image_id = m.image_id
        AND meta_value LIKE '%runner%'
        AND meta_key IN ('keyword', 'filename', 'description')    
)
ORDER BY m.image_id