重写查询以删除FIND_IN_SET?

时间:2010-06-04 13:01:56

标签: mysql query-optimization

我的mysql查询如下所示:

    SELECT pages.*,
           showcase.*,
           project.*    
      FROM pages
INNER JOIN showcase ON showcase.pid = pages.uid AND showcase.deleted != 1
INNER JOIN project ON FIND_IN_SET(project.uid, showcase.projects)   
     WHERE pages.deleted != 1
       AND pages.pid = 14
       AND pages.dokType = 150

问题是第二个INNER JOIN - 它使用FIND_IN_SET,因为showcase(=项目集合)将其项目存储为字段showcase.projects中的逗号分隔列表。据我所知,FIND_IN_SET无法使用索引,因此第二次连接需要对项目表进行全表扫描。是否有可能在不改变数据库方案的情况下使用索引?

2 个答案:

答案 0 :(得分:0)

showcase.projectsVARCHAR吗?然后你可以像这样使用REGEXP

...
INNER JOIN project ON
showcase.projects REGEXP CONCAT('[[:<:]]', project.uid, '[[:>:]]')
WHERE ...

这个表达式只查找整个单词(括号结构分别标记左右词边界。但是,我不确定这是否可以使用索引,也许有人可以想出更聪明的东西。

答案 1 :(得分:0)

您在另一个字符串中搜索“字符串”。无论如何,你都必须进行扫描。使用索引执行此操作的另一种优化方法是使用连接表。创建一个包含showcase_projectsproject_id列的新表showcase_id。然后,这将记录两者之间的每个关联。

现在,这个答案基于我对此查询中数据结构的原始理解。