加速大型数据库上的慢速SQL查询

时间:2016-09-10 19:31:30

标签: php sql

这是图片类型的网页

代码应选择具有最少量未分级图像的下一个标记。

表格信息

table_name = images

  • filename(varchar255)
  • pick(tinyint)
  • 拒绝(tinyint)

table_name = image_tags

  • filename(varchar255)
  • tag_name(varchar255)

索引

流动的列有索引:

  • images.filename
  • images.pick
  • images.reject
  • image_tags.filename

功能

代码应遍历每一行并检查有多少重复的tag_name-column。之后它应该返回具有最少重复行数的标记。代码应忽略pick = TRUEreject = TRUE

的所有行

意味着代码应仅包含pick = FALSEreject = FALSE

的文件

代码

目前,我的代码就在下面。

SELECT image_tags.tag_name, COUNT(*) as number_of_rows FROM image_tags JOIN images ON image_tags.filename = images.filename WHERE images.pick = FALSE AND images.reject = FALSE GROUP BY image_tags.tag_name ORDER BY number_of_rows

问题

由于数据库的大小,查询需要花费大量时间(有时多达30秒)。有没有办法让查询运行得更快,还是有另一个查询可以减少执行时间?

尺寸

  • images-table:700740行
  • image_tags-table:823852行

3 个答案:

答案 0 :(得分:1)

这是您的查询:

SELECT it.tag_name, COUNT(*) as number_of_rows
FROM image_tags it JOIN
     images i
     ON it.filename = i.filename
WHERE i.pick = FALSE AND i.reject = FALSE
GROUP BY it.tag_name
ORDER BY number_of_rows;

首先要尝试的是images(pick, reject, filename)上的索引。这可能无济于事,因为布尔列通常不会足够减少数据。但值得一试。

要尝试的第二件事是这个查询:

SELECT it.tag_name,
       (SELECT COUNT(*) 
        FROM images i
        WHERE it.filename = i.filename AND
              i.pick = FALSE AND
              i.reject = FALSE
       ) as number_of_rows
FROM image_tags it 
GROUP BY it.tag_name
ORDER BY number_of_rows;

这会将聚合移动到子查询,这有时在MySQL中表现更好。为此,您需要images(filename, pick, reject)上的索引。另请注意,这会返回所有标记,而不仅仅是具有匹配图像的标记。如果您希望获得与版本相同的结果,可以使用HAVING number_of_rows > 0进行过滤。

编辑:

哦,我明白了。你可以试试这个版本:

SELECT t.tag_name,
       (SELECT COUNT(*) 
        FROM image_tags it JOIN
             images i
             ON it.filename = i.filename
        WHERE it.tag_name = t.tag_name AND
              i.pick = FALSE AND
              i.reject = FALSE
       ) as number_of_rows
FROM (SELECT DISTINCT tag_name FROM image_tags) t 
ORDER BY number_of_rows;

为此,您需要image_tags(tag_name, filename)images(filename, pick, reject)上的索引。但是,我不确定这会有很大改善。

答案 1 :(得分:0)

确保为JOIN ON条件中使用的列创建了适当的索引; WHERE条件; ORDER BY。在您的情况下,您应该在

上创建索引

image_tags.filenameimages.filename images.pick; images.reject

还可以考虑为查询运行EXPLAIN,看看您获得的查询计划会更好。

EXPLAIN SELECT image_tags.tag_name, COUNT(*) as number_of_rows FROM image_tags ....

答案 2 :(得分:0)

由于images表具有int主键,因此将image_id作为image_tags表中的外键以及该列上的索引更有意义。 您将获得速度和存储空间。