MySQL 数据库中可搜索的用户名列使用什么数据类型和索引?
What data type and index to use for a searchable userName column in a MySQL database?
我有一个 MySQL 数据库,其中有一个名为 user
的 InnoDB table。
每个用户在创建帐户时都需要创建一个用户名。用户名的长度只能在 1 到 40 个字符 (utf-8) 之间。此用户名的用途是允许一个用户搜索另一个用户。
问题是我不确定用户名使用什么数据类型。由于用户名的长度可变,因此 Varchar
似乎很合适,但我不确定在 Varchar
上索引和搜索的速度有多快。我的想法是,因为我知道最大字符长度,所以我可以使用 Char(40)
代替。尽管由于填充,这会浪费一些 space,但我认为它会使索引和搜索更快、更高效,因为它是固定长度的。
我不确定的另一方面是我是否应该为该用户名列使用 Fulltext
索引或 BTree
索引。或者如果有其他我不知道的索引方法会更好。
那么与哪个索引相关的哪种数据类型会给我最好、最快和最具可扩展性的解决方案?
Char 与 Varchar
Char 在长度固定时很有用,例如产品参考或 ISO-* 字段。为什么 ?因为它会让你在每一行都使用 length byte。
但在您的情况下,名称绝不会超过 20 个字符,因此为了节省一个字节,您将在 75% 的记录中烧掉超过 20 个:这不是好方法。
当然是 Varchar。
索引 BTree 与全文
接下来是索引。如前所述,这取决于您将进行何种搜索。
对于使用 ='pattern'
或 LIKE 'pattern%'
的搜索,BTree 索引确实是最好的。
对于只做LIKE '%pattern%'
搜索字符串中的部分子串的搜索,那么,你真的什么都没有。
你能做的最好的事情就是拥有一个只映射 id = name
的“小”table,进行搜索并希望 mysql 将其保存在 RAM 中以执行顺序读取。
最后,您谈到了全文索引:该索引最适合匹配文本中的单词或单词的请求,因此对您来说可能与 BTree 的结果相同。
那么,最好的方法是什么?
可能是 BTree 索引。是的,您不会覆盖单词内的搜索,但在大多数情况下就足够了。
如何最好地使用它?
- 运行 第一次搜索
LIKE 'pattern%'
- 你有结果了吗?那么这可能就是用户想要的
- 没有?慢得多
LIKE '%pattern%'
改进:
- 允许用户检查直接进入第二次搜索的“内部词”修饰符
- 修复第一个查询的最小行数以避免第二个而不仅仅是严格的 0 结果
username VARCHAR(40) CHARACTER SET utf8mb4 NOT NULL
INDEX(username)
WHERE username = 'some_username'
这是唯一理智的答案。您最多需要 40 个 UTF-8 字符。用户将只搜索全名,不会搜索部分内容(LIKE
、FULLTEXT
等)。你需要索引,所以不用担心它比 INT
.
效率稍低
一个可能的变体:您可能希望 username
在某些 table 中成为 PRIMARY KEY
(而不是 'secondary' INDEX
)。
我有一个 MySQL 数据库,其中有一个名为 user
的 InnoDB table。
每个用户在创建帐户时都需要创建一个用户名。用户名的长度只能在 1 到 40 个字符 (utf-8) 之间。此用户名的用途是允许一个用户搜索另一个用户。
问题是我不确定用户名使用什么数据类型。由于用户名的长度可变,因此 Varchar
似乎很合适,但我不确定在 Varchar
上索引和搜索的速度有多快。我的想法是,因为我知道最大字符长度,所以我可以使用 Char(40)
代替。尽管由于填充,这会浪费一些 space,但我认为它会使索引和搜索更快、更高效,因为它是固定长度的。
我不确定的另一方面是我是否应该为该用户名列使用 Fulltext
索引或 BTree
索引。或者如果有其他我不知道的索引方法会更好。
那么与哪个索引相关的哪种数据类型会给我最好、最快和最具可扩展性的解决方案?
Char 与 Varchar
Char 在长度固定时很有用,例如产品参考或 ISO-* 字段。为什么 ?因为它会让你在每一行都使用 length byte。
但在您的情况下,名称绝不会超过 20 个字符,因此为了节省一个字节,您将在 75% 的记录中烧掉超过 20 个:这不是好方法。
当然是 Varchar。
索引 BTree 与全文
接下来是索引。如前所述,这取决于您将进行何种搜索。
对于使用 ='pattern'
或 LIKE 'pattern%'
的搜索,BTree 索引确实是最好的。
对于只做LIKE '%pattern%'
搜索字符串中的部分子串的搜索,那么,你真的什么都没有。
你能做的最好的事情就是拥有一个只映射 id = name
的“小”table,进行搜索并希望 mysql 将其保存在 RAM 中以执行顺序读取。
最后,您谈到了全文索引:该索引最适合匹配文本中的单词或单词的请求,因此对您来说可能与 BTree 的结果相同。
那么,最好的方法是什么?
可能是 BTree 索引。是的,您不会覆盖单词内的搜索,但在大多数情况下就足够了。
如何最好地使用它?
- 运行 第一次搜索
LIKE 'pattern%'
- 你有结果了吗?那么这可能就是用户想要的
- 没有?慢得多
LIKE '%pattern%'
改进:
- 允许用户检查直接进入第二次搜索的“内部词”修饰符
- 修复第一个查询的最小行数以避免第二个而不仅仅是严格的 0 结果
username VARCHAR(40) CHARACTER SET utf8mb4 NOT NULL
INDEX(username)
WHERE username = 'some_username'
这是唯一理智的答案。您最多需要 40 个 UTF-8 字符。用户将只搜索全名,不会搜索部分内容(LIKE
、FULLTEXT
等)。你需要索引,所以不用担心它比 INT
.
一个可能的变体:您可能希望 username
在某些 table 中成为 PRIMARY KEY
(而不是 'secondary' INDEX
)。