此查询将在缓存的自动填充文本框中完成,可能由数千名用户同时进行。我在下面的工作,我觉得可能有更好的方法来做我正在做的事情。
有什么建议吗?
更新 - 它可以是'某事'%':
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 '?%'
)
答案 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列都有一个索引,并且(如果现在该列上没有索引) ),查询性能将大大提高。