логин: 
<< предыдущая заметкаследующая заметка >>
06 марта 2010
Распухла таблица логинов...

Собственно говоря, у меня в дальних планах было привести ее в порядок. Ситуация в следующем: в таблице заводится учетная запись для КАЖДОГО посетителя. Так надо.

Но там куча полей для регистрации (имя, емайл, пароль, логин и т.п.), которыми большинство случайных посетителей никогда не воспользуется, поскольку не оставляют комментарии и не регистрируются. На данный момент учетных записей: 85662, из них пустых: 79089 (а если не считать поле lj, которое автоматом определяется, то и вовсе пустых 81445).

Варианта два:

1) Завести отдельную таблицу, куда записывать только личные данные пользователей, а в основной таблице оставить всего два поля int: собственно номер посетителя и, если не 0, ссылка на другую таблицу, где хранятся регистрационные поля.

2) Для «пустых» посетителей не хранить вообще учетной записи, а тупо пропускать нумерацию. Пусть останутся только заполненные записи: 80000,80007,80035, а если посетитель с присвоенным номером 80001 оставит о себе какую-то личную информацию, всегда можно завести учетную запись 80001.

Лично мне больше нравится вариант 2, но я не понимаю, как дать команду MySQL узнать, на чем остановился первичный индекс и увеличить его на единицу, не добавляя самой записи. И не возникнет ли сбоев, если два новых пользователя зайдут в одну секунду, и обоим будет в куку выдан одинаковый номер 80001 без записи в базу.

Еще можно оставить все как есть, но по крону чистить базу, удаляя пустые записи.

Что посоветуете?

<< предыдущая заметка следующая заметка >>
пожаловаться на эту публикацию администрации портала
Страницы, которые привлекли мое внимание за последние дни, рекомендую:
2017-11-22 В июне 1982
архив ссылок
Оставить комментарий
Windows Opera
1
0
anonymous (#3144)
Чистить раз в год. Миллиона пользователей там точно не будет. Если начнет тормозить, прикрутить индексы.
Windows Opera
0
0
anonymous (#3144)
Но вот "синхронизировать" первичный ключ в двух таблицах -- это очень плохая идея. Будут шальные глюки.
Windows Opera
0
0
Я бы начал с чистки. А там видно будет.
Windows Opera
1
0
Wot (#83640)
ну во первых зачем это все ?
- пустые поля, если varchar места много не занимают
- при наличии индекса на производительность не влияют
- было бы на 2 порядка больше - можно было бы потратить минут 10 на подумать, а так - минуты жалко

во-вторых, так все таки не делается.
- должен быть один id для пользователя и он на автоинкременте.
- если хочется вынести прочие данные в отдельную таблицу то там использовать тот же значение ключа, но без инкремента.
- цеплять ее через select * from t1 left join t2 on (t1.id=t2.id) - тогда будут NULL во всех дополнительных полях если нет записи в t2
- все это доп гиморрой в коде и он не стоит выгоды

в-третьих можно делать как считаешь нужным - свои грабли они ближе к телу. А следущее значение меняется через ALTER TABLE t2 AUTO_INCREMENT = value;
В варианте 2) напрашивается реализация через "sequences". MySQL в явном виде не поддерживает sequences, но их можно имитировать через отдельную таблицу с одной записью и единственным полем -- последним выданным id.

Cоздание:

CREATE TABLE sequence (id INT NOT NULL);
INSERT INTO sequence SELECT MAX(id) FROM accounts;

Получение нового id:

UPDATE sequence SET id=LAST_INSERT_ID(id+1);
SELECT LAST_INSERT_ID(); /* или через mysql_insert_id() */

Получение нового id будет атомарно в любом случае (два пользователя не могут получить одинаковые id), потому что обновление максимального id и его получение происходят за один запрос. LAST_INSERT_ID() / mysql_insert_id() просто возвращают ранее сохранённое (и уникальное для сессии) значение.
Linux Firefox
 Москва
1
0
Проблема в том, что заход нового посетителя - одна из самых серьезных нагрузок. Хотя бы потому, что это проявляется в пиковом режиме. Представьте, что какой-то ваш пост по какой-то случайности вдруг попал сегодня во все топы и обсуждается всюду. И к вам в дневник зашли не 30 обычных зарегистрированных френдов, а половина интернета.

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

У меня были надежды, что удастся обойтись вообще без записи в базу. Но, видно, пустые надежды.
Windows IE
0
0
sobomax (#4947)
Получение sequence это не запись в базу, вернее не совсем запись. Выполняется оно by design намного быстрее чем обычный INSERT или UPDATE, я думаю тысячи, если не десятки тысяч в секунду на современном железе не проблема, ну и отсутвие данного ID в индексе таблицы поможет со скоростью выборки существующих и вставки новых данных. Так что такой путь оптимизации вполне возможен и уместен.
Nokia-E90 Safari
 Москва
0
0
LLeo Nokia (#3043)
а как это? Я что-то не улавливаю
Windows IE
0
0
sobomax (#4947)
В mysql все немного через ж, там есть внутренний auto-increment (аналог объекта sequence в других базах). Напрямую он не доступен, однако его можно достать через stored function + таблицу из одной записи. Я там сслочку уже кидал на пример реализации такой функции. Использование подобного sequence весьма просто - "SELECT xxx_nextval()" чтобы атомарно получить новое уникальное значение для данной сессии, или "SELECT xxx_currval()" когда надо вытащить уже полученное ранее значение. Также nextval/currval можно использовать в INSERT/UPDATE, например: "INSERT INTO users (id, name) VALUES (users_currval(), 'Vasia Pupkin')".
Да, совсем без записи в базу не обойтись.

Если не хранить всех посетитителей, то номер последнего придётся хранить в любом случае. Как иначе можно быть уверенным в том, что новый id уже не выдавали раньше?

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

Как-то так.

И, присоединяясь к комментарию sobomax, я бы не стал волноваться о производительности в этом варианте. Это в любом случае эффективнее, чем то, что есть сейчас. Т.е. поддерживать индекс в очень рыхлой таблице -- куда большие накладные расходы при наплыве новых посетителей, чем простое увеличение поля в однострочной таблице.
Windows IE
0
0
sobomax (#4947)
Ээээ, сорри я признаться кажется забыл что в мускле последовательностей встроенных не реализованно. Пользование правильными транзакционными БД (postgresql) развращает. Впрочем реализация счетчика последовательности на базе таблицы из одной записи вполне может оказаться по скорости сравнима с тем что делается специальными средствами в других местах - апдейты в mysql весьма быстрые, особенно если тип таблицы myisam. Вот тут рецепт как реализовать sequence() таким образом:

http://forums.mysql.com/read.php?61,143867,244029#msg-244029

Быстрый тест на стареньком четырехмоторном сервере p4-based xeon показывает вполне приличную производительность порядка 6,000 вызовов R_ObjectId_nextval() в секунду.
И именно поэтому я этот объект и предлагаю. ;) Точнее его эмуляцию средствами MySQL.

То была попытка объяснить, почему совсем без записи в базу не обойтись.
Минимальную реализацию sequence я уже привёл. А то, что по ссылке -- это ужас какой-то. Stored function + insert + delete + user variable? Нет, спасибо :)
Функция удобна тем что при ее использовании проще будет потом портировать код на другой сервер БД, постгрес или оракл какой-нибудь. :)
Windows Opera
1
1
gryzchick
Вообще, СУБД не касается, есть ли в поле запись или нет. Место резервируется в любом случае. Когда требуется выбрать, например, запись под номером 78300, она не парсит подряд весь файл, в котором находится искомое, а вычисляет смещение в байтах, на котором находится искомая строка. Даже если все 78299 записей до этой пусты, СУБД все равно начнет читать с одной и той же позиции в файле.
Windows Firefox
2
0
№1 куда как проще, следовательно правильнее
Windows Opera
1
0
[email protected] (217888993625)
+1
Linux Firefox
 Москва
0
0
Проще - на каком этапе? На этапе проектирования или переделки готового движка? С переделкой всех частей и созданием модулей для апгрейда баз у других пользователей движка?
Windows Opera
0
0
[email protected] (217888993625)
Таблицы типа InnoDB обеспечивают безопасное выполнение транзакций. Транзакция гарантирует отсутствие наложений.
Windows Opera
3
0
[email protected] (217888993625)
Цитирую по книге: "наличие большого количества нулевых значений в базе данных - плохая практика. Большинства таких проблем можно избежать, воспользовавшись иным подходом к проектированию."

всего комментариев: 20

<< предыдущая заметка следующая заметка >>