每列的多列索引与索引? MySQL的

时间:2015-03-29 11:32:52

标签: mysql sql database indexing

我有这张表:

业务表:

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来搜索أ اة ه字母不区分大小写(在添加测试单词之前我也会替换这些字母)。

我的问题:

  1. 我想知道如何正确声明索引!
  2. 我应该声明多列index:

    ALTER TABLE `bussiness` 
    ADD INDEX `index9` (`nameHe` ASC, `nameEn` ASC, `nameAr` ASC, `favor` ASC, `bussStatus` ASC);
    
    每个col的

    或一列索引!

    1. 我应该创建另一个包含allNamesLanguages的col nameAr,nameEn,nameHe然后我只搜索此col?

2 个答案:

答案 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 - 可能还有updatedelete个触发器,用于在插入新值时替换特殊字符。也就是说,大量replace( . . . )逻辑在触发器中。
  • 为四列添加全文索引。
  • 使用match . . . against查询。

有关全文功能的更多信息,请参见documentation

答案 1 :(得分:0)

函数基本上使索引无用。因此,WHEREUPPER(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' ...