MySQL-主键的字符串比较速度

MySQL-主键的字符串比较速度,mysql,Mysql,我有一个MySQL表,我希望我的主键是一个字符串。此字符串可能稍长(数百个字符) 一个非常常见的查询是插入。。。在重复键更新时,这意味着MySQL必须经常检查表中是否已经存在主键。如果这是用一个简单的strcmp完成的,我想字符串越长,这可能需要相当长的时间。因此,手动对字符串进行散列(短字符串或其他数据类型)并将其用作主键更好吗?还是直接使用长字符串更好?MySQL是否在内部散列主键字符串?首先,当您在varchar字段上有索引时,MySQL不会对所有条目执行strcmp以找到正确的条目;相反

我有一个MySQL表,我希望我的主键是一个字符串。此字符串可能稍长(数百个字符)


一个非常常见的查询是
插入。。。在重复键更新时,这意味着MySQL必须经常检查表中是否已经存在主键。如果这是用一个简单的strcmp完成的,我想字符串越长,这可能需要相当长的时间。因此,手动对字符串进行散列(短字符串或其他数据类型)并将其用作主键更好吗?还是直接使用长字符串更好?MySQL是否在内部散列主键字符串?

首先,当您在varchar字段上有索引时,MySQL不会对所有条目执行strcmp
以找到正确的条目;相反,它使用一个比strcmp快得多的方法来导航以找到正确的条目

注意:如果需要,我会在下面提供一些信息来提高性能,但是在遇到实际问题之前,请不要这样做。Varchar索引很快,很多非常聪明的人都对其进行了优化,在大多数情况下,它将远远超出您的需要

话虽如此,如果您有很多条目和/或很长的键,那么在其上使用散列索引是一种很好的性能明智选择

CREATE TABLE users
(
    username varchar not null,
    username_hashed varchar(32) not null,
    primary key (username),
    index (username_hashed)
);
例如,插入时可以设置
username\u hashed=md5(username)
。然后用类似于
的东西搜索,从username\u hashed=md5(username)和username=username的用户中选择其他字段


请注意,这似乎可以让您不必手动执行此操作。

首先,当您在varchar字段上有索引时,mysql不会对所有条目执行strcmp
,以找到正确的条目;相反,它使用一个比strcmp快得多的方法来导航以找到正确的条目

注意:如果需要,我会在下面提供一些信息来提高性能,但是在遇到实际问题之前,请不要这样做。Varchar索引很快,很多非常聪明的人都对其进行了优化,在大多数情况下,它将远远超出您的需要

话虽如此,如果您有很多条目和/或很长的键,那么在其上使用散列索引是一种很好的性能明智选择

CREATE TABLE users
(
    username varchar not null,
    username_hashed varchar(32) not null,
    primary key (username),
    index (username_hashed)
);
例如,插入时可以设置
username\u hashed=md5(username)
。然后用类似于
的东西搜索,从username\u hashed=md5(username)和username=username的用户中选择其他字段


请注意,它似乎允许您不必手动执行此操作。

主键是否需要是字符串?它难道不能是一个唯一的索引,具有一个整数主自动增量吗

使用整数搜索总是会更快,并且可能需要在应用程序中重新安排一些代码,但搜索带编号的主键和字符串总是会更好。 看看这两篇文章,它们显示了int和varchar的内存差异:


主键需要是字符串吗?它难道不能是一个唯一的索引,具有一个整数主自动增量吗

使用整数搜索总是会更快,并且可能需要在应用程序中重新安排一些代码,但搜索带编号的主键和字符串总是会更好。 看看这两篇文章,它们显示了int和varchar的内存差异:


你不会单枪匹马地击败拥有数百万行代码和数百名观察者的代码库。让MySQL做它自己的事情吧。阅读这里,你不会单枪匹马地超过一个拥有数百万行代码和数百个观察者的代码库。让MySQL来做它的事情吧。在这里我想+1作为你答案的第一部分,但是你的
username\u hashed=md5(username)
建议很糟糕。除了可能出现重复条目外,添加列只会降低速度,因为需要(a)计算和存储列,以及(b)维护列上的索引。@Denis:在检查哈希值和实际值时,重复并不是一个真正的问题(因此,即使有冲突——我同意你最终会有冲突,mysql也只能匹配几个条目,而不是整个索引)。我发现,虽然它会降低插入速度(主键没有更新),一旦它达到数百万个长字符串,它将非常好地提高选择速度。我想这取决于您的需要,因此我会发出粗体的警告,如果可能的话,我会使用更明智的设计,但如果没有,这会有所帮助。“当您检查哈希值和实际值时,复制不是一个真正的问题”--但是,主键的索引总是会被使用,而散列值根本不会被使用--除了通过添加一个单独的检查来减慢查询速度。或者MySQL真的尝试对散列值使用索引吗?@Denis:你的问题让我在使用了一年的pg之后重新阅读MySQL,这种行为可能已经改变了。当时,它确实改变了使用散列索引,但这是mysql 5的早期版本,需要在现代版本上进行测试才能确认。你确定散列检查比只检查纯文本快吗?文本可以按长度跳过,所有散列都相同。答案的第一部分是+1,但你的
username\u hashed=md5(username)
这个建议很糟糕。除了可能出现重复条目外,添加列只会降低速度,因为需要(a)计算和存储列,以及(b)维护列上的索引。@Denis:在检查哈希值和实际值时,重复并不是一个真正的问题(因此,即使有冲突——我同意你最终会有冲突,mysql也只能匹配几个条目,而不是整个索引)