MySQL多重连接导致极端缓慢

时间:2016-08-02 15:56:26

标签: mysql sql performance

我试图导出(在表格中)我们网站中使用的所有 NOT 图像。我的工作代码在小数据集上运行良好,但仍然没有从我们超过4,000张图像的数据集中返回结果。我在select语句中有类似的代码:

SELECT a.id, a.image_name, a.last_modified, c1.val
    FROM a 
    /*file name could be used in table 'r' in the image1, image2, or image3 fields*/
    LEFT JOIN r ON a.image_name = r.image1 
        OR a.image_name = r.image2
        OR a.image_name = r.image3
    /*file name could be used anywhere within c.val field*/
    LEFT JOIN c c1 ON c1.val LIKE CONCAT('%', a.image_name,'%')
    /*get the page_id where the image name is found in c*/
    LEFT JOIN p p1 ON p1.page_id = c1.page_id   
    WHERE a.type = 'Image'  /*only images on this query*/
    AND r.image1 IS NULL /*no references in r.image1*/
    AND r.image2 IS NULL /*no references in r.image2*/
    AND r.image3 IS NULL /*no references in r.image3*/
    AND c1.val IS NULL /*no references in c.val OR...*/
    /*in the page where it was found, see if the page is a deleted page*/
    OR a.id NOT IN (SELECT a.id FROM a 
        LEFT JOIN c c2 ON c2.val LIKE CONCAT('%', a.image_name, '%')
        LEFT JOIN p p2 ON p2.page_id = c2.page_id
        WHERE p2.deleted IS NULL) /*deleted IS NULL means the page is not deleted*/
    ORDER BY a.last_modified DESC

在此导出中显示图像时,实际上有两种情况:

  1. 找不到任何地方
  2. 在已删除的页面中找到它
  3. 第一个是通过外部SELECT减去OR a.id NOT IN...部分获得的。第二个是使用内部SELECT获得的,我确保id未包含在未删除的页面中。

    我已经尝试将OR a.id NOT IN...更改为OR p1.deleted IS NOT NULL以取消内部SELECT的开销,但这会给我所有在已删除页面中找到的图像,不一定是图像仅在已删除的页面中找到。

    我尝试索引p.deleted,r.image1,r.image2和r.image3字段而不提高效率。我也试过制作BLOB字段,c.val,一个FULLTEXT索引,但也没有帮助。

    a.id,a.image_name,c.page_id和p.page_id已经编入索引。

    同样,这是有效的代码,但我只是想提高性能,以便我们可以使用完整的数据集将代码投入生产。感谢您提前回复任何回复。

1 个答案:

答案 0 :(得分:1)

对于我在评论中开始的野鹅追逐感到抱歉,我应该仔细查看一下查询;但这可能会有所帮助......

SELECT a.id, a.image_name, a.last_modified, c1.val
FROM a 
LEFT JOIN (
    /*file name could be used in table 'r' in the image1, image2, or image3 fields*/
    SELECT 1 AS matched, image1 AS image FROM r
    UNION SELECT 1, image2 FROM r
    UNION SELECT 1, image3 FROM r
) AS r2 ON a.image_name = r2.image
/*file name could be used anywhere within c.val field*/
LEFT JOIN c c1 ON c1.val LIKE CONCAT('%', a.image_name,'%')
/*get the page_id where the image name is found in c*/
LEFT JOIN p p1 ON p1.page_id = c1.page_id   
WHERE a.type = 'Image'  /*only images on this query*/
AND r2.matched IS NULL /*no references in r.image1, r.image2, or r.image3*/
AND (
    c1.val IS NULL /*no references in c.val OR...*/
    /*in the page where it was found, see if the page is a deleted page*/
    OR a.id NOT IN (
        SELECT a.id 
        FROM a 
            LEFT JOIN c c2 ON c2.val LIKE CONCAT('%', a.image_name, '%')
            LEFT JOIN p p2 ON p2.page_id = c2.page_id
        WHERE p2.deleted IS NULL
    ) /*deleted IS NULL means the page is not deleted*/
)
ORDER BY a.last_modified DESC