2013-06-01 2 views
0

У меня есть таблица MySQL, где я бы хотел, чтобы мой первичный ключ был строкой. Эта строка может быть немного длиннее (сотни символов).MySQL - скорость сравнения строк для первичного ключа

Очень распространенный запрос будет INSERT ... ON DUPLICATE KEY UPDATE, что означает, что MySQL должен будет проверить, существует ли первичный ключ в таблице. Если это делается с наивным strcmp, я предполагаю, что это может занять некоторое время, чем дольше строки. Было бы лучше ли хэш строки вручную (либо более короткой строкой, либо некоторым другим типом данных) и использовать это как мой первичный ключ, или я могу просто использовать длинную строку напрямую? Является ли MySQL первичными ключевыми строками MySQL внутри?

+1

Вы не собираетесь в одиночку перехитрить базу кода похваляясь миллионы строк и сотни наблюдатели. Пусть MySQL выполнит свою задачу. –

+2

Читайте здесь http://stackoverflow.com/questions/517579/strings-as-primary-keys-in-sql-database – Yogus

ответ

3

Прежде всего, когда у вас есть указатель на поле varchar, mysql не делает strcmp на все записи, чтобы найти правильный; вместо этого он использует binary tree, который намного быстрее, чем strcmp, чтобы найти подходящую запись.

Примечание: я включаю некоторую информацию для повышения производительности, если это необходимо ниже, но , пожалуйста, не делайте этого, пока не нажмете на актуальную проблему. Индексы Varchar бывают быстрыми, они оптимизированы множеством очень умных людей, и в подавляющем большинстве случаев это будет больше, чем вам нужно.

С учетом сказанного, если у вас много записей и/или очень длинных ключей, может быть приятным показателем, чтобы использовать индекс хэшей поверх него.

CREATE TABLE users 
(
    username varchar not null, 
    username_hashed varchar(32) not null, 
    primary key (username), 
    index (username_hashed) 
); 

При установке вы можете установить, например, username_hashed = md5(username). И затем вы ищете что-то вроде select otherfields from users where username_hashed = md5(username) and username = username

Обратите внимание, что это mysql 5.5 support hash index natively, что позволит вам не делать этого вручную.

+0

Я бы добавил +1 для первой части вашего ответа, но ваше 'username_hashed = md5 (имя пользователя) 'предложение ужасное. Помимо возможности дублирования записей, добавление столбца просто замедляет работу из-за накладных расходов, связанных с необходимостью (а) расчета и хранения и (б) поддерживать индекс на нем. –

+0

@Denis: дубликат на самом деле не проблема, так как вы проверяете хэш, а затем фактическое значение (поэтому, даже если у вас есть коллизии, и я согласен с вами в конечном итоге, mysql затем должен сопоставлять только пару записей вместо весь индекс). И я обнаружил, что, хотя он замедляет вставки немного (без обновления первичного ключа), он дает очень хороший импульс в выборе скорости, когда он достигает миллионов длинных строк. В зависимости от ваших потребностей, я думаю, таким образом, мое смелое предупреждение, и, если возможно, я использовал бы более удачный дизайн, но если это не поможет. – Lepidosteus

+0

«дубликат на самом деле не является проблемой при проверке хэша, а затем фактического значения», но тогда индекс первичного ключа всегда будет использоваться, а хешированное значение не будет использоваться вообще, за исключением медленного запрос вниз, добавив отдельную проверку. Или MySQL действительно пытается использовать индекс для хеширования? –

0

Должен ли первичный ключ быть строкой? Разве он не может быть уникальным индексом с целым начальным автоматическим приращением?

Поиск всегда будет быстрее с целыми числами, и это может привести к перестройке кода в вашем приложении, но вам всегда будет лучше искать нумерованные первичные ключи и строки. Посмотрите на эти две должности, которые показывают разницу в памяти для междунар и VARCHAR:

What is the size of column of int(11) in mysql in bytes?

Memory usage of storing strings as varchar in MySQL

Смежные вопросы