2009-09-08 8 views
1

У меня есть большая таблица MySQL InnoDB (около 1 миллионных записей, увеличение на 300 тысяч в неделю), скажем, с сообщениями в блоге. В этой таблице есть поле url с индексом.Использование MD5 (URL) вместо URL-адреса в DB для WHERE

Добавляя в него новые записи, я проверяю существующие записи с тем же адресом. Вот как запрос выглядит следующим образом:

SELECT COUNT(*) FROM `tablename` WHERE url='http://www.google.com/'; 

система В настоящее время производит около 10-20 запросов в секунду, и эта сумма будет увеличена. Я думаю об улучшении производительности, добавив дополнительное поле, которое является хешем MD5 URL.

SELECT COUNT(*) FROM `tablename` WHERE md5url=MD5('http://www.google.com/'); 

Таким образом, он будет короче и с постоянной длиной, которая лучше для индекса по сравнению с полем URL. Что вы, ребята, думаете об этом. Имеет ли это смысл?

Другое предложение моего друга - использовать CRC32 вместо MD5, но я не уверен, насколько уникальным будет результат CRC32. Позвольте мне знать, что вы думаете о CRC32 для этой роли.

UPDATE: столбец URL уникален для каждой строки.

ответ

4

Создайте некластеризованный индекс по URL-адресу. Это позволит вашему SQL-движку выполнять внутреннюю оптимизацию и даст наилучшие результаты!

Если вы создаете индекс в столбце VARCHAR, SQL будет создавать хэш внутри, и использование индекса может дать лучшую производительность на порядок или даже больше!

Кроме того, что-то иметь в виду, если вы только проверить, существует ли URL, является то, что некоторые продукты SQL будет производить более быстрые результаты с запросом, как это:

IF NOT EXISTS(SELECT * FROM `tablename` WHERE url='') 
    -- return TRUE or do your logic here 
+1

Я думал, что «некластеризованная» была терминологией SQL Server - не следует ли считать, что это просто индекс? –

+0

некластеризованные индексы являются «виртуальными» индексами данных, тогда как кластеризованные индексы являются физическими индексами данных. У вас может быть только один кластеризованный индекс для каждой таблицы, в то время как вы можете иметь несколько некластеризованных индексов в одной таблице –

+0

Согласовано, индекс NC будет иметь такую ​​же или аналогичную производительность, что и добавление MD5 или другого хэша. Если у вас высокое отношение записей таблиц на URL-адресе, я бы рассмотрел структуру двух таблиц, в которой поддерживаются уникальные URL-адреса, например, tblUrls и tablename будут хранить только соответствующий ключ. Это может немного увеличить производительность вставки, а также уменьшить требования к хранению и иметь несколько других преимуществ в зависимости от основного приложения. – mjv

0

Я думаю, что CRC32 на самом деле будет лучше для этой роли, так как она короче и экономит больше пространства SQL. Если вы получаете много запросов, объект должен сэкономить место? Если это сработает, я бы сказал, иди за ней.

Несмотря на то, что он всего лишь 32-битный и более короткий по длине, он не так уникален, как MD5, конечно. Вам нужно будет решить, хотите ли вы уникально или хотите сэкономить место.

Я все еще думаю, что я бы выбрал CRC32.

Моя система генерирует примерно 4 тыс. Запросов в секунду, и я использую CRC32 для ссылок.

+0

Вы всегда можете сохранить полный URL-адрес в отдельном столбце и попросить MySQL сравнить как тот же CRC32, и тот же полный URL. –

+0

Попробуй это, спасибо! : P – Homework

-1

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

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

0

Используя индексацию сборки в всегда лучше, или вы должны добровольно добавить их кодовую в любом случае;)

При использовании хэш, создать индекс на 2 колонки на хэш и URL.Если вы выбираете только первую пару букв в индексе, она все равно выполняет полное совпадение, но не индексирует больше первых букв.

Что-то вроде этого:

INDEX(CRC32_col, URL_col(5)) 

Либо хэш будет работать в этом случае. Это компромисс между космосом и скоростью.

Кроме того, этот запрос будет намного быстрее:

SELECT * FROM table WHERE hash_col = 'hashvalue' AND url_col = 'urlvalue' LIMIT 1; 

Найдет первое значение и остановится. Гораздо быстрее, чем найти много совпадений для вычисления COUNT (*).

В конечном счете лучшим выбором является создание тестовых примеров для каждого варианта и эталонных тестов.

-1

Если вы выберете хэш, вам нужно учитывать коллизии. Даже при большом хеше, таком как MD5, вы должны учитывать вероятность meet-in-the-middle, более известную как birthday attack. Для меньшего хэша, такого как CRC-32, вероятность столкновения будет довольно большой, и ваш WHERE должен указать хэш и полный URL.

Но я должен спросить, это лучший способ потратить ваши усилия? Нечего еще оптимизировать? Возможно, вам удастся сделать преждевременную оптимизацию, если у вас нет четких показателей и измерений, указывающих на то, что эта проблема является узким местом системы. В конце концов, такой поиск - это то, для чего оптимизируются базы данных (все они), и делая что-то вроде хэша, вы можете фактически снизить производительность (например, ваш индекс может стать фрагментированным, потому что хеши имеют разное распределение, чем URL-адреса).

0

Не большинство систем SQL используют хеш-функции для поиска столбцов текста?

0

Если вы собираетесь использовать хешированные ключи, и вас беспокоят столкновения, используйте две разные функции хеширования и объедините два хешированных значения.

Но даже если вы это сделаете, вы всегда должны хранить значение ключа в строке.

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

  • Нет связанных вопросов^_^