[БД] Identity-поле: автоинкремент vs. GUID
я почти тоже самое хотел из личного опыта написать
The uniqueidentifier data type has several disadvantages:
The values are long and obscure. This makes them difficult for users to type correctly, and more difficult for users to remember.
The values are random and cannot accept any patterns that may make them more meaningful to users.
There is no way to determine the sequence in which uniqueidentifier values were generated. They are not suited for existing applications that depend on incrementing key values serially.
At 16 bytes, the uniqueidentifier data type is relatively large compared to other data types such as 4-byte integers. This means indexes built using uniqueidentifier keys may be relatively slower than implementing the indexes using an int key.
Основное преимущество Guid - это его децентрализация, что позволяет использовать гибкие схемы редактирования, обработки данных и т.д.
это да
По моему элементарно сделать децентрализацию на 4-байтном идентификаторе?
как?
это вопрос или что?
Ну не знаю, пишут же malloc без mutex-ов Условно говоря, первый байт номер сервера, на трех остальных автоинкремент. Не подходит?
централизацию ты не убрал, ты просто ее сместил на уровень процесса:
a) отдельные процессы все также должны где-то регистрироваться,
b) код внутри процесса должен работать через единый класс раздачи id-ей.
децентрализация, что позволяет использовать гибкие схемы редактирования, обработки данных и т.д.Вот тут можно несколько конкретных примеров?
Пока я осознал один плюс использования GUID'ов - то, что Identity становится известным ещё до внесения в базу.
Хотелось бы увидеть более-менее явное и четкое преимущество GUID в каких-то конкретных задачах. Вроде "вот тут с GUID очень удобно, а с инкрементом не очень или вообще нельзя или очень хитро нужно извернуться, чтобы можно было".
Обратным примерам тоже буду рад.
так именно это часто и используется.
1. так , например, прямо на клиенте - можно заводить/редактировать большой кусок связанных данных
2. можно делать кэши на запись
3. можно разносить прозрачно один справочник - по нескольким базам, можно потом его сливать обратно и т.д.
4. также очень удобна глобальная уникальность:
например, есть у нас толпа таблиц: машины, люди, дома и т.д., и т..п.
далее - нам надо добавить какой-то общий сервис, например, права на редактирование
и в случае guid-ов - мы при введение этого сервиса - можем использовать те же самые id-ы, которые были выданы элементам раньше, в случае - автоинкремента (придется заводить какой-то фиктивный ключ: имя таблицы + id)
Любопытно, спасибо.
1. так , например, прямо на клиенте - можно заводить/редактировать большой кусок связанных данныхНа клиенте лучше совсем ничего не делать.
2. можно делать кэши на запись
3. можно разносить прозрачно один справочник - по нескольким базам, можно потом его сливать обратно и т.д.Интересно, часто возникает необходимость делать такие странные вещи?
4. также очень удобна глобальная уникальность:Пример реален, да.
например, есть у нас толпа таблиц: машины, люди, дома и т.д., и т..п.
далее - нам надо добавить какой-то общий сервис, например, права на редактирование
и в случае guid-ов - мы при введение этого сервиса - можем использовать те же самые id-ы, которые были выданы элементам раньше, в случае - автоинкремента (придется заводить какой-то фиктивный ключ: имя таблицы + id)
Но в общем все это как-то неубедительно звучит.
На клиенте лучше совсем ничего не делать.поясни теперь это утверждения, помня, что в даннм случе под "клиентом" может подразумеваться business-logic tier в multitier приложениях, т.е. главное то, что ид генерит не хранилище, а бизнес логика. Хранилище то как раз должно быть тупым - его задача хранить и предоставлять данные.
Интересно, часто возникает необходимость делать такие странные вещи?Например, мы разносим бд по нескольким физическим серверам для повышения производительности. Вполне реальная задача. О "частоте" говорить без конеткста имхо бессмысленно.
> Интересно, часто возникает необходимость делать такие странные вещи?
Довольно часто, если задача, например, распределенная.
Магазин - в урюпинске, склад - в москве, головной офис - в лондоне.
Ошибку понял, для распределенных приложений guid возможно предпочтительней, да.
4. также очень удобна глобальная уникальность:сомнительный пример
например, есть у нас толпа таблиц: машины, люди, дома и т.д., и т..п.
далее - нам надо добавить какой-то общий сервис, например, права на редактирование
и в случае guid-ов - мы при введение этого сервиса - можем использовать те же самые id-ы, которые были выданы элементам раньше, в случае - автоинкремента (придется заводить какой-то фиктивный ключ: имя таблицы + id)
во первых: никто и ничто вам не мешает использовать один глобальный автоинкрементый ключ на всю базу, а не для каждой таблицы отдельно.
во вторых: как, простите, в твоем примере ты при редактировании прав будешь определять, что это такое редактируется: машина или человек? а поределять это надо хотя бы для того чтобы вывести название объекта - т.о. таблицу все равно придется знать.
в третьих: получить значение очередного значения для автоинкремента ничуть не сложнее, чем гуид.
в четвертых: на клиенте никаких идентификаторов генерить нельзя потому как это уязвимость, кривость и нарушение концепции многозвенности.
напомню, что у меня шла речь - про идентификацию (primary key у тебя идет речь - как по ключу получить необходимые данные.
это разные вещи.
> получить значение очередного значения для автоинкремента ничуть не сложнее, чем гуид.
много сложнее, потому что необходим прямой мгновенный доступ к единому центру.
> на клиенте никаких идентификаторов генерить нельзя потому как это уязвимость, кривость и нарушение концепции многозвенности
допустим - id-ы выдаются даже прямо на клиенте
в чем же здесь нарушение концепции многозвенности?
с уязвимостью - вообще - не понятно, в чем она состоит.
т.к. база, вроде. как раз и должна отслеживать такие нарушения целостности.
например, DataSet-ы это хендлят, используют локальный автоинкремент, а при сохранении в базу значения локального автоинкремента во всех связанных сущностях заменяется на автоинкремент из базы. Но есть неудобство, нельзя использовать CommandBuuilder.
1. так , например, прямо на клиенте - можно заводить/редактировать большой кусок связанных данных
Вообщем, если ломает возиться с автоинкрементом и если длинна гуида не мешает, то можно использовать гуид. Длинна гуида мешает, когда критична время выполнения запросов с использованием этого индекса. Объем базы тоже может увеличиваться на процентов 20-30. Трафик по сети тоже больше.
с уязвимостью - вообще - не понятно, в чем она состоит.Пусть у нас есть распределенная система управления телеканалами. В одной системе завязаны все каналы, все управление ими и пр. - т.е. "серьезная" система.
т.к. база, вроде. как раз и должна отслеживать такие нарушения целостности
Злоумышленники установили на все компьютеры в региональных телестудиях "плохих" клиентов. А еще они узнали MAC-адрес компа, который отдает команды на начало показа телепередач на ОРТ (несложная задача для любого человека из их локальной сети).
Плохие клиенты в количестве больше 1000 штук начинают генерировать guid-ы из интервала 23:55:00-23:59:59 на 31 декабря 2006 года (т.е. сильно заранее). Работают они слаженно и коллизий внутри плохих клиентов при генерации id-шников не возникает, поэтому никто и не думает, что у нас что-то не так. Не думает вплоть до 31 декабря 2006 года, когда на ОРТ не смогло начаться новогоднее обращения президента России из-за того, что на главной машине с правильным (!) клиентом пытаются сгенерить id-шник начинающегося показа - коллизия, еще раз - опять.
И все. Новый год не начнется, лето никогда не наступит. Полный привет.
в количестве больше 1000а что это за количество?
1000 - это нижняя оценка количества компов в региональных телеканалах.
В гуиде аж целых 16 байт. Из них 6 - в мак-адресе. Остаётся 10. Допустим, они считают время в 100-наносекундных тиках, как все нормальные люди, и засовывают их в 8 байт. А ещё два заполняют рандомами. Отлично! А теперь посчитаем, сколько гуидов нужно сгенерить, чтобы полностью забить 10 секунд: 10 * 1000 * 1000 * 10 * 2^16 = 10^8 * 2^16 > 2^27 * 2^16 = 2^43.
База не лопнет?
Кстати, а я правильно понимаю, что int в мсскуль-базе 32битный, так что такое количество записей туда поместиться не может в принципе?
но, это отказ в доступе, а не уязвимость уровня некорректного доступа к данным, или некорректного изменения данных.
> генерировать guid-ы из интервала 23:55:00-23:59:59 на 31 декабря 2006 года
всего guid-ов в этом интервале, если не ошибаюсь - 10^7 * 60 * 5 = 3 * 10^9
имхо, база от такого кол-ва там, где ожидались всего десятки таких записей - ляжет раньше, чем дойдет очередь до Нового Года.
в целом - проблема, конечно, есть, но реальное использование очень сложное и полученный результат небольшой - поэтому на системах низкой и средней важности - guid-ы можно генерить даже на клиенте.
для важных систем - Guid можно также генерить на клиенте, лишь надо проверять, что клиент такой guid имел право создать.
Каждый из 1000 компов круглосуточно генерит по 100 инсертов в секунду (у нас толстая база, она не лопнет). Вася Пупкин на новый год решил сорвать следующий новый год и запустил генерацию. Он успеет сгенерить log(2, 3153600000000) = 2^41.5 гуидов, а нужно чуть больше 2^43! Вывод, генерить придётся как минимум пять лет.
Можно просто поточнее узнать время начала. А вообще, никто и не скрывает, что пример - чистейшая паранойа. Я обычно именно guid-ами пользуюсь.
Оставить комментарий
bobby
Почитал один из соседних тредов и задумался.Хотелось бы услышать доводы (желательно поконкретнее и с примерами) в пользу использования автоинкрементальных identity или GUID в к-ве identity в таблицах БД. Рассмотрю любые соображения, даже самые нелепые/очевидные, возможно, какие-то ситуации из личного опыта пишущих в разделе и т.п.
Спасибо.