我有这张表:
业务表:
bussId | nameEn | nameHe | nameAr | status | favor | cityId | categoryId
类别表:
categoryId | keywords
最喜欢的表:
userId | bussId
评级表:
userId | bussId | rating
我正在运行此查询,使用cityId过滤商家并搜索(business.nameEn,business.nameAr,business.nameHe,categories.keywords),然后按fav,order和nameEn排序。
SELECT DISTINCT bussID ,businessName, bussStatus,favor, ratingCount , ratingSum
FROM
(
SELECT DISTINCT business.bussID , business.nameEn as businessName , bussStatus,favor,
(SELECT COUNT(rating.bussId) FROM `rating` WHERE rating.bussId = business.bussID) as ratingCount ,
(SELECT SUM(rating.rating) FROM `rating` WHERE rating.bussId = business.bussID) as ratingSum
FROM business LEFT JOIN favourites ON (favourites.bussID = business.bussID AND favourites.userID = '30000')
INNER JOIN `categories` ON (`categories`.`categoryId` = `business`.`subCategoryId` )
WHERE (bussiness.cityID = 11)
AND (
( REPLACE( REPLACE(REPLACE(LOWER(`bussiness`.`nameEn`),'أ','ا'),'أ','ا') ,'ة','ه') LIKE '%test%' )
OR( REPLACE( REPLACE(REPLACE(LOWER(`bussiness`.`nameHe`),'أ','ا'),'أ','ا') ,'ة','ه') LIKE '%test%' )
OR( REPLACE( REPLACE(REPLACE(LOWER(`bussiness`.`nameAr`),'أ','ا'),'أ','ا') ,'ة','ه') LIKE '%test%' )
OR( REPLACE( REPLACE(REPLACE(LOWER(`categories2`.`keyWords`),'أ','ا'),'أ','ا') ,'ة','ه') LIKE '%test%' )
)
AND
(bussiness.bussStatus IN(1,3,5,7)
)
GROUP BY bussiness.bussID )results
ORDER BY
businessName LIKE '%test%' DESC,
FIELD(bussStatus,'1','5','3'),
FIELD(favor,'1','2','3'),
businessName LIMIT 0,10
我使用replace来搜索أ ا
和ة ه
字母不区分大小写(在添加测试单词之前我也会替换这些字母)。
我的问题:
我应该声明多列index:
ALTER TABLE `bussiness`
ADD INDEX `index9` (`nameHe` ASC, `nameEn` ASC, `nameAr` ASC, `favor` ASC, `bussStatus` ASC);
每个col的或一列索引!
allNamesLanguages
的col nameAr,nameEn,nameHe
然后我只搜索此col?答案 0 :(得分:1)
查询的这一部分存在两个问题,导致标准索引无法使用:
( REPLACE( REPLACE(REPLACE(LOWER(`bussiness`.`nameEn`),'أ','ا'),'أ','ا') ,'ة','ه') LIKE '%test%' )
OR( REPLACE( REPLACE(REPLACE(LOWER(`bussiness`.`nameHe`),'أ','ا'),'أ','ا') ,'ة','ه') LIKE '%test%' )
OR( REPLACE( REPLACE(REPLACE(LOWER(`bussiness`.`nameAr`),'أ','ا'),'أ','ا') ,'ة','ه') LIKE '%test%' )
OR( REPLACE( REPLACE(REPLACE(LOWER(`categories2`.`keyWords`),'أ','ا'),'أ','ا') ,'ة','ه') LIKE '%test%' )
首先是在列上使用函数。第二个是使用like
,其模式以通配符('%'
)开头。
对于您似乎想要的功能,您将需要使用全文索引和触发器以及其他列。
以下是我的建议:
business.nameEn_search
等等。insert
- 可能还有update
和delete
个触发器,用于在插入新值时替换特殊字符。也就是说,大量replace( . . . )
逻辑在触发器中。match . . . against
查询。有关全文功能的更多信息,请参见documentation。
答案 1 :(得分:0)
函数基本上使索引无用。因此,WHERE
等UPPER(name)
子句中使用的列可以通过所谓的基于函数的索引"进行索引。它们是Oracle的一个特性,但据我所知,不是在MySQL中。
How to use a function-based index on a column that contains NULLs in Oracle 10+?
http://www.mysqlab.net/knowledge/kb/detail/topic/oracle/id/5041
但基于函数的索引有其先决条件。使用的功能必须是确定性的。因此,如果您想对" age"等计算进行索引,那么它就不会起作用,因为" age"定义为"现在减去"每次选择时基本上都会增长。
我的建议是尽可能准备创建更多列并存储要在那里开采的信息。
如果使用LIKE "%blabla%"
,由于文本起始长度可变,任何索引都将无用。因此,请尝试组织其他列,以便您可以避免LIKE "%...
或完全避免LIKE
。根据我的经验,为索引添加更多列不会成为许多列的性能限制因素。所以,试试如果为它们添加4列和一个组合索引会发生什么。
据我所知,你可以在写完后赢得游戏:
... WHERE nameEn_idx = 'test' AND/OR nameEr_idx = 'test' ...