MySql 本例为单列索引或多列索引

MySql single column index or multi-column index in this case

我有以下简化的 table 'places',其中包含 200,000 多行:

placeId INT(10)
placeName VARCHAR (30)
placeNameEnglish VARCHAR (30)

目前我有两个单列索引 - 一个用于 placeName,一个用于 placeNameEnglish,并且正在执行这些 LIKE 模式查询:

$testStr = 'rho';

SELECT placeId
FROM places
WHERE (placeName LIKE '$testStr%' OR placeNameEnglish LIKE '$testStr%')

进行了一些研究,但在这种情况下使用时无法完全理解多列索引。问题是,我应该将 placeNameplaceNameEnglish 组合成一个多列索引还是将它们保留为单独的索引?

更新

正在努力实施@Gordon Linoff 建议的最后一个建议。

考虑添加一个名为 translations 的 table 而不是 placeNames,这样同一个索引可以用于多个 table,即 persons table 需要相同的 LIKE 'abc%' 匹配。

到目前为止:

transId INT

parentId INT - placeIdpersonId

parentTypeId TINYINT - 1 识别 places table 或 2 识别 persons table 等(更多 table 以后可以使用此系统)

languageId INT

transName VARCHAR

我是否还应该为 parentTypeId 编制索引以适应识别正确父项 table 所需的额外 WHERE 条件?

例如WHERE transName LIKE 'abc%' AND parentTypeId = 1

我想象 mysql 是这样工作的:它首先使用 transName 的索引来匹配 transName LIKE 'abc%',然后使用 parentTypeId = 1[=43 过滤结果=]

对于此查询:

SELECT placeId
FROM places
WHERE placeName LIKE '$testStr%' OR placeNameEnglish LIKE '$testStr%';

MySQL 可以 使用两个索引,一个在 places(placeName) 上,一个在 places(placeNameEnglish) 上。该操作称为索引合并(请参阅 here)。我不会指望它。该查询不能完全使用复合索引。

您可以将查询改写为:

SELECT placeId
FROM places
WHERE placeName LIKE '$testStr%'
UNION
SELECT placeId
FROM places
WHERE placeNameEnglish LIKE '$testStr%';

或:

SELECT placeId
FROM places
WHERE placeName LIKE '$testStr%'
UNION ALL
SELECT placeId
FROM places
WHERE placeId NOT IN (SELECT placeId FROM places WHERE placename LIKE '$testStr%') AND
      placeNameEnglish LIKE '$testStr%';

这些可以利用两个索引。

不过,我的建议是更改数据的结构。有一个名为 PlaceNames(或类似名称)的 table,其中包含以下列:

placeNameId INT
placeId INT,
languageId INT,
placeName VARCHAR(255)

也就是说,每种语言各占一行。然后,您的查询可以轻松利用 placeName(placeName).

上的索引

对于您原来的问题:两个独立的索引。但是……你太辛苦了:

对于欧洲地名,您不需要搜索这两列。 utf8_unicode_ci(或 utf8_bin 以外的几乎任何排序规则)的大小写折叠和重音不敏感将满足您的需要:

mysql> SELECT 'Rhône' LIKE '%rho%', 'Rhône' LIKE '%xyz%';
+-----------------------+-----------------------+
| 'Rhône' LIKE '%rho%'  | 'Rhône' LIKE '%xyz%'  |
+-----------------------+-----------------------+
|                     1 |                     0 |
+-----------------------+-----------------------+

编辑 根据 OP 的评论,这不是一个完整的解决方案。