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