MySQL - 更好的方法来执行此查询?

时间:2010-09-07 22:13:01

标签: mysql sql

此查询将在缓存的自动填充文本框中完成,可能由数千名用户同时进行。我在下面的工作,我觉得可能有更好的方法来做我正在做的事情。

有什么建议吗?

更新 - 它可以是'某事'%':

SELECT a.`object_id`, a.`type`, 
    IF( b.`name` IS NOT NULL, b.`name`,
        IF( c.`name` IS NOT NULL, c.`name`, 
            IF( d.`name` IS NOT NULL, d.`name`,
                IF ( e.`name` IS NOT NULL, e.`name`, f.`name` )
            )
        )
    ) AS name
FROM `user_permissions` AS a 
   LEFT JOIN `divisions` AS b 
       ON ( a.`object_id` = b.`division_id` 
           AND a.`type` = 'division' 
           AND b.`status` = 1 ) 
   LEFT JOIN `departments` AS c 
       ON ( a.`object_id` = c.`department_id` 
           AND a.`type` = 'department'  
           AND c.`status` = 1 ) 
   LEFT JOIN `sections` AS d 
       ON ( a.`object_id` = d.`section_id` 
           AND a.`type` = 'section'  
           AND d.`status` = 1 ) 
   LEFT JOIN `units` AS e 
       ON ( a.`object_id` = e.`unit_id` 
           AND a.`type` = 'unit'  
           AND e.`status` = 1 ) 
   LEFT JOIN `positions` AS f 
       ON ( a.`object_id` = f.`position_id` 
           AND a.`type` = 'position'  
           AND f.`status` = 1 ) 
WHERE a.`user_id` = 1 AND ( 
    b.`name` LIKE '?%' OR
    c.`name` LIKE '?%' OR
    d.`name` LIKE '?%' OR
    e.`name` LIKE '?%' OR
    f.`name` LIKE '?%'
)

3 个答案:

答案 0 :(得分:3)

两个简单,快速的查询通常比一个巨大的,低效的查询更好。

以下是我的设计方法:

首先,使用FULLTEXT索引以MyISAM格式为您的所有名称创建一个表。这就是你的名字存储的地方。每个相应的对象类型(例如,部门,部门等)都是从属表,其主键引用主命名对象表的主键。

现在,您可以使用这个更简单的查询来搜索名称,该查询运行速度非常快:

SELECT a.`object_id`, a.`type`, n.name, n.object_type
FROM `user_permissions` AS a 
JOIN `named_objects` AS n ON a.`object_id = n.`object_id`
WHERE MATCH(n.name) AGAINST ('name-to-be-searched')

使用全文索引将比您使用LIKE的速度快数百次。

获得对象ID和类型后,如果您需要相应对象类型的任何其他属性,则可以执行第二 SQL查询,以连接到表以获取相应的对象类型:

SELECT ... FROM {$object_type} WHERE object_id = ?

这也会非常快。


重新评论:是的,我创建了包含名称的表,即使它是多余的。

答案 1 :(得分:1)

你可以做500件事。一旦知道瓶颈在哪里就可以优化。在此之前,努力让这些用户加入您的应用。它的优先级更高。

答案 2 :(得分:1)

除了更改嵌套的Ifs以使用Coalesce()函数(MySql有Coalesce()不是吗)?只要您需要使用like表达式对输入参数进行过滤,您就无能为力。使用Like表达式对列进行过滤,其中Like参数在开头有一个通配符,就像你一样,使查询参数不具有SARG能力,这意味着查询处理器必须对< em> all 表中的行以评估过滤谓词。

它不能使用索引,因为索引基于列值,而使用Like参数,它不知道要读取哪些索引条目(因为参数以通配符开头)

如果MySql具有Coalesce,您可以将Select替换为:

SELECT a.`object_id`, a.`type`,
Coalesce(n.name, c.name, d.Name, e.Name) name

如果你可以替换搜索参数参数,使它不以通配符开头,那么只需确保每个表中的name列都有一个索引,并且(如果现在该列上没有索引) ),查询性能将大大提高。