【问题标题】:multiple columns index vs index for each col ? mysql多列索引与每个列的索引? mysql
【发布时间】:2015-03-29 11:32:51
【问题描述】:

我有这张桌子:

业务表:

bussId | nameEn | nameHe | nameAr | status | favor | cityId | categoryId 

分类表:

categoryId | keywords

最喜欢的表:

userId | bussId

评分表:

userId | bussId | rating

我正在运行此查询,它使用 cityId 过滤企业并搜索(business.nameEn、business.nameAr、business.nameHe、categories.keywords),然后按青睐、状态和 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

我正在使用替换来搜索不区分大小写的 أ اة ه 字母(在添加测试词之前,我也替换了这些字母)。

我的问题:

  1. 我想知道如何正确声明索引!

我应该声明多列索引吗:

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

或每个列的一个列索引!

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

【问题讨论】:

  • 并不是说“业务”是这样拼写的。至于索引,为什么不吸进去看看呢?
  • @Strawberry 我怎么知道我的查询使用了哪些索引!
  • EXPLAIN 会告诉你(我的意思是'note',而不是'not')

标签: mysql sql database indexing


【解决方案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

【讨论】:

  • 感谢您的回复,如果我创建一个组合 3 列的列“nameEn_nameAr_nameHe_search”,那么只需创建一个索引!这样好吗?
  • 2 问题:我正在使用 Innodb 引擎,使用全文和匹配 ... 是否有问题?。
  • 谢谢,那么创建一个包含四列的列,然后为该列创建一个全文?
  • 哦,根据dev.mysql.com/doc/refman/5.6/en/fulltext-restrictions.htmlmysql需要5.6.4及更高版本,但我使用的是5.6.21b :(
【解决方案2】:

函数基本上使索引无用。因此,WHERE 子句中使用的列,如 UPPER(name) 和 else,可以通过所谓的“基于函数的索引”进行索引。它们是 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

不过,基于函数的索引有其先决条件。使用的函数必须是确定性的。因此,如果您想为“年龄”之类的计算编制索引,它不会起作用,因为定义为“现在减去那时”的“年龄”基本上每次选择时都会增长。

我的建议是创建更多列并将要挖掘的信息存储在那里,尽可能做好准备。

如果你使用LIKE "%blabla%",任何索引都将因为文本开始长度可变而无用。因此,请尝试组织其他列,以便您可以避免LIKE "%... 或完全避免LIKE。根据我的经验,向索引添加更多列不会成为许多列的性能障碍。因此,只需尝试为它们添加 4 列和一个组合索引会发生什么。

据我了解,只要你能写,你就赢了:

... WHERE nameEn_idx = 'test' AND/OR nameEr_idx = 'test' ...  

【讨论】:

  • 感谢您的回复,但这对我没有帮助,因为根据您的查询,名称为 testXY 的商家将不会被退回!
  • 还要注意排序规则 utf8_unicode_ci 和 utf8_persian_ci 做大小写折叠。因此UPPER()LOWER() 是不必要的。
猜你喜欢
  • 1970-01-01
  • 2011-11-07
  • 2010-09-15
  • 2018-07-27
  • 1970-01-01
  • 2011-01-21
  • 2020-05-06
  • 1970-01-01
相关资源
最近更新 更多