Является ли разделение таблицы «пользователи» для целей аутентификации хорошей идеей?

8

Предположим, у меня на сайте есть таблица пользователей, в которой около 2-3 миллионов пользователей (записей).

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

Если мы можем запустить запрос, аналогичный приведенному ниже, из одной таблицы:

select username,password from users where username=`test` AND password=****

Необходимо ли разделить его, и ускоряет ли это процесс входа в систему моего сайта?

ALH
источник
1
Добавив это просто как комментарий, так как это не прямой ответ на ваш вопрос. Возможно, это то, что вы делаете, помимо вашего примера запроса, но хранить пароли в вашей базе данных - очень плохая практика. Вы хотите сохранить их как has, а затем сделать запрос, например, где password_hash = hash ($ userEnteredPassword)
atxdba
@atxdba Я фактически хэшировал их, но здесь я только что привел пример.
ALH

Ответы:

10

ИМХО Тебе не нужно физически его разбивать. Тем не менее, было бы неплохо его кешировать.

Если в usersтаблице используется MyISAM Storage Engine, у вас есть хорошее преимущество.

Поскольку MyISAM кэширует только индексы, вы можете сделать две вещи

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

Убедитесь, что следующие индексы существуют для users

ALTER TABLE users ADD UNIQUE INDEX username_ndx (username);
ALTER TABLE users ADD UNIQUE INDEX username_password_ndx (username,password);

Есть две (2) основные причины для двух индексов

ПРИЧИНА для индекса № 1

Индекс не username_ndxпозволяет имени пользователя иметь несколько паролей, а также запрещает нескольким пользователям с одним именем

ПРИЧИНА для индекса № 2

Индекс username_password_ndxобеспечивает индекс покрытия . Таким образом, ваш запрос будет искать имя пользователя и пароль только в пользовательском кэше MyISAM вместо проверки таблицы.

Дополнительные ссылки на принципы покрытия индексов

Следующее, что нужно сделать, - создать этот кеш. Вот команды для создания 8 МБ кеша ключей и загрузки этого выделенного кеша ключей (пример: если таблица mydb.users):

SET GLOBAL authentication_cache.key_buffer_size = 1024 * 1024 * 8;
CACHE INDEX mydb.users IN authentication_cache;
LOAD INDEX INTO CACHE mydb.users;

Вы должны поместить эти три строки в файл /var/lib/mysql/startup.sql

Добавьте это в /etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/startup.sql

Это будет загружать кэш каждый раз при запуске mysql

Попробуйте!

ОБНОВЛЕНИЕ 2011-12-30 17:25 ПО ВОСТОЧНОМУ ВРЕМЕНИ

Если вы хотите получить точный размер для установки кэша, используйте следующий запрос:

SELECT CONCAT('1024 * 1024 * ',ROUND(index_length/power(1024,2))) RecommendedCacheSize
FROM information_schema.tables WHERE table_name='users';

ОБНОВЛЕНИЕ 2011-12-30 23:21 ПО ВОСТОЧНОМУ ВРЕМЕНИ

Вот метод, основанный на InnoDB

Вам все еще нужны индексы

ALTER TABLE users ADD UNIQUE INDEX username_ndx (username);
ALTER TABLE users ADD UNIQUE INDEX username_password_ndx (username,password);

Вы должны убедиться, что в пуле буферов InnoDB есть имена пользователей и пароли. Возможно, вам придется прибегнуть к полному сканированию индекса при запуске mysql:

Шаг 1) Создайте ReadUserPass.sql

echo "select username,password from users;" > /var/lib/mysql/ReadUserPass.sql

Шаг 2) Добавьте этот скрипт в /etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/ReadUserPass.sql

Шаг 3) Выполните одно из следующих

  • $ service mysql restart
  • mysql> source /var/lib/mysql/ReadUserPass.sql

Поскольку оба эти столбца (имя пользователя и пароль) находятся в username_password_ndx, все страницы индекса, составляющие этот индекс, перезагружаются в пул буферов InnoDB. Это необходимо, потому что существует возможность удаления страниц индекса. Чтобы свести к минимуму это, увеличьте размер пула буферов и перезапустите mysql (один раз).

RolandoMySQLDBA
источник
На самом деле я использую движок хранения InnoDB, но я думаю, что процесс кеширования будет в порядке, не так ли @RolandoMySQLDBA?
ALH
Нет. Шаги в моем ответе только MyISAM.
RolandoMySQLDBA
Если usersтаблица участвует в транзакциях, то мне нужно отправить другой ответ, основанный исключительно на InnoDB.
RolandoMySQLDBA
Извините, я не упомянул об этом, я не знал, что у них будут разные подходы!
ALH
Я ответил на основе MyISAM, потому что я хотел, чтобы таблица пользователей кэшировалась в своем собственном ключевом буфере.
RolandoMySQLDBA
5

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

mrdenny
источник
Эх, какой был размер оперативной памяти?
Чибузе Опата
3

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

Аарон Браун
источник
1
Что вы подразумеваете под «вы уверены, что мне нужно решить более серьезные проблемы»?
ALH
1
Не имеет смысла решать проблемы, когда мы знаем, что в ближайшем будущем мы столкнемся с множеством проблем. Эта проблема является головной болью, когда в таблице много данных! -1 для тебя.
ALH
2
Моя точка зрения двояка ... не оптимизируйте, прежде чем вам понадобится & 2 миллиона записей не очень много. Индекса будет много.
Аарон Браун
2

Если вы используете Mysql 5.1 и выше, вы можете попробовать разбить таблицу на части.
Что касается вашего вопроса о том, ускоряет ли он процесс входа в систему, это зависит от того, как выглядит оставшаяся часть процедуры входа в систему (например, если ваш запрос теперь занимает 0,05 секунды, а остальная часть кода занимает 20 секунд, я бы предпочел повторно думаю вся рутина ...).
Кроме того, независимо от использования разделов, не забудьте добавить индексы, как указал RolandoMySQLDBA .

a1ex07
источник
Хороший вызов для определения фактической причины проблем с производительностью перед оптимизацией. Часто это не там, где мы думаем. Доказательный тюнинг - это путь!
Стюарт Вудворд