在包含逗号分隔值的varchar字段上创建索引是否合适?

时间:2014-03-25 08:13:57

标签: mysql

我正在创建一个存储大量数据的小型数据库。 该表有一个列,它将以varchar格式存储外键(例如1,12,13 ...),这样我就可以一次性获取数据。 因此,如果我将列索引到主表的主键,这是否重要。 (我只是索引而不是创建外键引用)

2 个答案:

答案 0 :(得分:1)

为了解释一下索引,请参考以下示例。

分类

Id  Category
1   Cat A
2   Cat B
3   Cat C
4   Cat D
5   Cat E
6   Cat F

用户

Id  Name    CategoryList
1   Bill    1,2,3
2   Burt    4,5,6
3   Jill    1,3,5
4   Alli    2,4,6

如果users表中的categories字段有索引,如果是这样的话: -

1,2,3   1
1,3,5   3
2,4,6   4
4,5,6   2

如果您查找“1,3,5”,则可以轻松按顺序搜索该表并找到匹配的ID。它可以(例如)跳转到索引的一半并检查它所寻找的值是高还是低。然后重复该过程以查找所需的记录。

但是,如果搜索包含类别2的行(如下所示),则2可能位于字符串中的任何位置,则无法使用索引。

SELECT Users.Name, Categories.Category
FROM Users
INNER JOIN Categories
ON FIND_IN_SET(Category.Id, Users.CategoryList)
WHERE Categories.Category = 2

FIND_IN_SET不能使用索引,因为它检查的值可能位于该逗号分隔列表中的任何位置。相反,它必须检查每一行并查找逗号分隔值为2的那一行。在SQL中手动拆分字符串(这是可能的)肯定会更有效,但与使用索引相比速度慢

例如,如果您有1000行,每行有1000个逗号分隔的ID,并且您希望列表中包含id为123的单行,则FIND_IN_SET需要读取1000行,将这些行中的每一行拆分并检查这些行值为123,所以1000000比较(加上分割逗号分隔列表的处理)。如果id在索引字段中独立,则接近1比较。

如果表格是: -

分类

Id  Category
1   Cat A
2   Cat B
3   Cat C
4   Cat D
5   Cat E
6   Cat F

用户

Id  Name    
1   Bill    
2   Burt    
3   Jill    
4   Alli    

UsersCategories

Id  UserId  CatId
1   1       1
2   1       2
3   1       3
4   2       4
5   2       5       
6   2       6
7   3       1
8   3       3
9   3       5
10  4       2
11  4       4
12  4       6

你可以在整数字段上有一个索引(速度很快),你可以简单地进行连接: -

SELECT Users.Name, Categories.Category
FROM Categories
INNER JOIN UsersCategories
ON Categories.Id = UsersCategories.CatId
INNER JOIN Users
ON UsersCategories.UserId = Users.Id
WHERE Categories.Category = 2

这可以很容易地在每个比较/连接上使用索引来提供可观的性能。

编辑 - 以下将为您提供所有用户的列表,并为每个用户列出他们拥有的类别: -

SELECT Users.Name, GROUP_CONCAT(Categories.Category)
FROM Users
LEFT OUTER JOIN UsersCategories
ON UsersCategories.UserId = Users.Id
LEFT OUTER JOIN Categories
ON Categories.Id = UsersCategories.CatId
GROUP BY Users.Name

答案 1 :(得分:0)

在支持VARCHAR索引的MySQL中,您可以继续创建它。

然而,MysqL为索引设置的空间量存在约束,对于MyISAM,长度最多可达1000个字节,对于InnoDB表,最长可达767个字节。因此,在数据增长的情况下,索引可能不受支持且无法有效使用。可以在以下网址找到可能的解释:

http://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html

如果您想要一些替代方法来处理您的数据库,您可以给这篇文章读一读:

https://dba.stackexchange.com/questions/35821/possible-index-on-a-varchar-field-in-mysql