Pull to refresh

Comments 204

ИМХО борьба с ветряными мельницами, причем сначала вы рассказываете почему AIPK это зло потом в примере показываете что не использовать PK не так уж и просто а выгоды вообще не видно, ИМХО реальная ситуация когда AIPK-зло это таблицы n:m, ну и очень частные случаи в которых это и так очевидно
мое личное правило простое, если в таблице присутствует UNIQUE_KEY — автоинкремент 99% лишний и будет вносить путаницу.
Согласен, если он не многоколоночный. Тогда все не так празднично.
Не согласен. Хорошая практика держать И автоинкрементый айди И уникальный натуральный ключ. Причины: ID удобен для внутренних операций, сложного процессинга. джойны. Передача айдишников в Web Clientside UI.

NK удобны в внешних интеграционных интерфейсах. И для поиска сущностей из разных бизнес воркфлоу.
допустим, таблица пользователей с уникальным полем username(VARCHAR[64]).
два момента:
1. Вы будете в таблице articles делать index author_username(VARCHAR[64])?
2. Что будет, если вы вдруг решите поменять username пользователю на другой?
зайдите на фейсбук и попробуйте поменять логин ;)
и что? а в моём уютненьком бложике можно поменять себе никнейм. хотя поле все-равно unique
ок, отнесем ваш случай к тому 1% который я оставил
в phpbb можно поменять имя пользователя. это тоже ничего не значит?
а фейсбук будет в качестве foreign key использовать варчар поле? думаете, это не несет за собой проблем с производительностью?
вопрос был «а если я захочу поменять логин», я указал на то что например fb считает что «вы не должны этого хотеть»… все
UFO just landed and posted this here
Что-то вас обманывает… Используют они релляционные базы и еще как. В частности, даже MySQL используют и даже делают для нее патчи. Также как, впрочем, и noSQL и т.д. Эти ребята очень умны, они не гонятся за модой — они делают моду =)
UFO just landed and posted this here
В MySQL facebook вроде в основном логи хранит. В общем все технологии нужны. Релляционные БД пока никто не отменял, хотя во многих случаях noSQL-storages удобнее.
Не только логи, а большую часть контента.
UFO just landed and posted this here
Да, но… это ж совсем другое. Представьте себе форум вроде PHPBB на NoSQL.
UFO just landed and posted this here
Насколько я понимаю, в key-value бд varchar уже не такой varchar :-)
о поводу (2)
Что будет, если вы вдруг решите поменять username пользователю на другой?
в статье отмечено:
Действительно, некоторые СУБД не умеют выполнять ON UPDATE CASCADE или делают это слишком неэффективно (кстати, подумайте об этом как о причине смены СУБД).
Т.е. обновлением ссылок при изменении поля внешнего ключа должен заниматься ON UPDATE CASCADE этого внешнего ключа. Другой вопрос, что его в 99% случаев игнорируют.
Отлично. И вместо единичного апдейта set username = :new_username получаем десятки, а возможно и тысячи неявных апдейтов по разным таблицам + операции с индексами. Причем вместо простого int все эти операции мы делаем с varchar(N).
Угу, с одной стороны. С другой стороны — это причина из серии premature optimizaition.
если возможность изменения username заложена в проекте, то это не premature.
Немного позанудствую (Вы сами виноваты). :) Слово premature переводится как «преждевременная», а не как «ненужная».

Пока не проверена и не доказана необходимость оптимизировать вообще, и конкретно в этом месте проекта в частности — любая оптимизация будет преждевременной. Простой пример: если ваш проект не очень популярен, и его база весит пару мегабайт — каскадное обновление не будет узким местом. Второй пример: громадная база, популярнейший проект… но за пять лет его существования только три пользователя воспользовались фичей смены своего логина.
Вы немного утрируете. С такой логикой можно все поля делать varchar(255), а данные складывать в одну супертаблицу, отложив нормализацию до тестов производительности. Здравый смысл и опыт должны присутствовать, и это не преждевременная оптимизация (именно так я и перевел)
Всё верно, я сам действую именно так. Но я из любопытства года три назад начал пристрастно наблюдать за тем, что мне советует мой здравый смысл и опыт (21 год софт пишу)… и с удивлением обнаружил, что большой опыт в данном случае довольно часто играет против меня самого, заставляя заранее оптимизировать (читай — усложнять) то, что в данном конкретном проекте в оптимизации пока явно не нуждается, и не факт что будет нуждаться. Просто когда-то где-то в другом проекте я на грабли в этом месте уже наступал, поэтому во всех новых проектах «преждевременно» предохраняюсь.

Когда я это обнаружил, и стал активно «хватать себя за руки» и «непущать» делать преждевременные оптимизации — простота кода однозначно выросла, и проблем из-за этого пока не возникало. Да, в некоторых случаях позднее приходилось таки сделать пару оптимизаций, которые «напрашивались» с самого начала. Но пришлось сделать пару, а напрашивалось их пару десятков.
Думаю, что powerman прав в данном случае. Именно это и имел ввиду Беркус. С вашей точки зрения получается, что здравый смысл у разработчиков www.bricolage.cc отсутствует напрочь.
Причина в данном случае только одна — создание стройной масштабируемой архитектуры БД, которая будет доставлять минимум геморроя при эксплуатации и развитии.
А откуда тысячи апдейтов, кстати? Ну десятки я еще понимаю, но тысячи?
Возьмем этот надуманный пример про пользователей.

Допустим, у конторы есть учетная система. Пользователи создают и изменяют в ней документы (заявки, накладные, счета,… ). Допустим, этих документов будет 10. У каждого документа есть ссылка на пользователя, который его создал. Кроме этого, ведется история изменения в данных. Предположим, что 100 пользователей за день производят по 100 действий в базе — 10 000 в день…
… и тут кладовщица, проработавшая три года, решила выйти замуж и сменить фамилию, которая одновременно является и её логином. Да от неё одной в базе будет несколько десятков тысяч хвостов.
Хвостов — да, но не апдейтов. Апдейтов будет по одному на таблицу, которая содержит внешний ключ для той, в которой изменяется значение. Разумеется, если мы берем случай, где такие изменения производятся часто — выбор естественного ключа будет, скорее всего (!) неудачным. А что, если в системе такие изменения вообще производиться не должны по каким-то причинам? Или, например, причина их производить появляется крайне редко? Скорее всего (!) ничего плохого от выполнения одного запроса на обновление данных на каждую таблицу, который, к тому же, затрагивает очень малый процент данных, не случится.

Обратите внимание, что я говорю «скорее всего», потому что не существует универсальных решений. И нечего спорить попусту. Ситуации бывают совершенно различными.
Разве кто-то спорит? Последние два поста были в стиле вопрос-ответ.
Кстати, предложений update будет по одному на таблицу, верно, но физических операций изменения записей будет столько, сколько строк изменяет этот апдейт. Плюс операции по изменению индекса на внешнем ключе (если он есть, конечно. А по рекомендациям лучших собаководов быть он должен).

За сим, позвольте прекратить «спор» вашими же словами: «не существует универсальных решений… ситуации бывают совершенно различными».
Принимается :) Еще бы прекратить подобные же споры здесь в других ветках :)
обновлением ссылок при изменении поля внешнего ключа должен заниматься ON UPDATE CASCADE этого внешнего ключа. Другой вопрос, что его в 99% случаев игнорируют.

и правильно делают, т.к. изменения могут быть очень масштабными.
А могут и не быть, не так ли? Поэтому Беркус и говорит, что в большинстве случаев за принятием решения не стоит никаких тестов или других серьезных соображений.
провели тесты — все зашибись, тормозов нет.
не факт что так и будет всегда и со временем не появятся новые, более тяжелые связи.
Одно дело, если они «появятся, может быть. А может, и не появятся». И другое, когда они «появятся обязательно, это вопрос времени». Если вы предполагаете, что они появятся в любом случае — можно провести тесты, поскольку обычно смоделировать данные для тестов достаточно просто.

Следуя вашей логике, если брать Facebook — они должны были еще в самом начале отказаться от PHP, когда только поняли, что начнут хоть немного расти. Но они решили проблему по-другому (HIPHOP).
Чтобы проанализировать, смоделировать, протестировать нужно время, а конкретная задача, как правило, имеет четко поставленные цели и сроки. «Может быть» подразумевает ненулевую вероятность возникновения такой ситуации и если она возникнет, то, скорее всего, во время эксплуатации, когда исправление ошибки в разы дороже, чем во время разработки. Использование же суррогатного ключа исключает такие ситуации и дополнительное поле + индекс не такая большая плата за это.

Может быть, я не прав, но в том, что вы предлагаете, если возможно, не тратить время на анализ, моделирование и тестирование, я с вами не согласен.
CASCADE UPDATE мы можем сделать в рамках одной базы.
А если нам потребуется идентифицировать пользователя в других базах? Плюс, например, прямого доступа к этим базам нет, а только через web-сервис.
Тогда назвать этот ключ «суррогатным» уже нельзя. Он становится частью данных.
Плюс еще все не только прямого доступа нет, а все эти базы вообще работают только на INSERT, а UPDATE и DELETE в них запрещен по соображениям производительности. И API на изменение никто не писал или оно недоступно. А если все доступно, просто и легко сделать?

Не нужно придумывать странные ситуации, а потом доказывать, что если на этой конкретной ситуации подход не работает, он заведомо плох.
Мне кажется, вы невнимательно прочитали пост. Во-первых, это не я рассказываю, а Джош Беркус. А из того, что я показывал на своем примере видно, что суррогатные ключи в моем случае по большей части были не нужны. Я их там наставил совершенно незачем. Может быть, вам это кажется примитивным. Мне тоже сейчас. Но довольно большому количеству читателей это может быть интересно. Я ж попросил — если вы опытный, не расстраивайте себя, просто пройдите мимо :)
Надеюсь довольно большое кол-во читателей реально представляет как и где и зачем нужно использовать суррогатные ключи… )
Надеюсь довольно большое кол-во читателей реально представляет себе что такое суррогатные ключи… )
Я вот вроде бы внимательно прочитал, но так и не понял суть ошибки в описании таблицы log. Что там не так?

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

Или все-таки лишним было само поле log_occured_on? Тоже, казалось бы, нет — точное время несет полезную информацию при рассмотрении логов, хотя на ключевое поле и не тянет вроде.
Вообще время никогда не стоит использовать в качестве ключа.

Пару примеров:
Точного времени на большинстве серверов нет (http://system-administrators.info/?p=1359)
Время может «убегать», например сисадмин промахнется при переводе часов.
Время на разных серверах может расходится до 1-2 сек.

А вот теперь рассмотрим ситуацию:
У нас есть таблица Юридических Лиц. Есть 2 Уникальных Реквизита — ИНН, ОГРН. Все вот он — наш случай. Скажем НЕТ суррогату, но через пол года в базе появляется НЕРЕЗИДЕНТ, а у него данных реквизитов нет. Все наша БД запись вставит не дает, тети кричат, сисадмины в ужасе звонят разработчику, разработчик поднимает программистов и дает по шапке, разработчики в ужасе ищут статью на хабре.

Большинство случаев требует наличие первичного ключа из-за вероятности не уникальных данных, которые при ближнем рассмотрении кажутся 100% уникальными.

Каждый торрент имеет так называемый info_hash, который его уникальным образом идентифицирует.

Любой хеш — это свертка текста в него, она по определению НЕ УНИКАЛЬНА.
Хеширование применяется для сравнения данных: если у двух массивов хеш-коды разные, массивы гарантированно различаются; если одинаковые — массивы, скорее всего, одинаковы. В общем случае однозначного соответствия между исходными данными и хеш-кодом нет в силу того, что количество значений хеш-функций меньше чем вариантов входного массива; существует множество массивов, дающих одинаковые хеш-коды — так называемые коллизии. Вероятность возникновения коллизий играет немаловажную роль в оценке качества хеш-функций.
®
ну правильно :)

тогда наступит случай нахождения дубликата ))
это как раз то, что нужно, чтобы не хранить два одинаковых торрента в разных записях

а INSERT IGNORE нам поможет
тогда наступит случай нахождения дубликата ))

существует множество массивов, дающих одинаковые хеш-коды определение выше
Это означает, то торренты будут СОВЕРШЕННО РАЗНЫЕ.

Только ни трекер, ни клиенты не будут в курсе насколько я понимаю спецификации битторрента.
да, я понимаю, о чем Вы

но выигрыш от исключения добавления в таблицу дубликата торрента (а в случае суррогатного ключа с автоинкрементом дубликат будет добавлен в любом случае) чисто имхо больше, чем шанс получить коллизию торрента (это при количестве параметров, учитывающихся при хешировании в торренте)
>(это при количестве параметров, учитывающихся при хешировании в торренте)
Разве оно влияет на шанс коллизии? Вроде бы при подобных алгоритмах важна только длина хэша.
А с коллизией хэша в любом случае сойдут с ума трекер (который сервер, обслуживающий пиров) и клиент.
не сходите с ума. Дубликат sha1 (а именно он используется в торрентах) до сих пор не найден.
Ну, вообще-то, наличие коллизий никак не отрицает утверждения «дубликат не найден». Судя по вашей же ссылке опубликованы лишь разные версии атаки (описаны алгоритмы взлома). Цифры вычислительной сложности приведены огромные и в данный момент время работы этих «алгоритмов» выражается в миллиардах лет.
Но теоретически, разумеется, существует множество исходных недублирующихся торрентов, у которых одинаковые хеш-коды. Это утверждение — тоже факт. Другое дело, что вероятность этого стремится к нулю. И если для подписи SHA-1 уже скомпрометирован, то как хеш-функция он по-прежнему вполне годится.
Это коллизия любых двух разных наборов данных с одинаковым хешем стремится к нулю. А чтобы два торрента (со своей внутренней структурой) оказались с одним хешем — это оно не просто стремится, а стремглав устремляется к нулю)

Слона надо есть частями. Тут проблемы нет.
Если на трекере будет два торрента с одинаковым info_hash, их нельзя будет раздать.
Да какая это проблема. Пусть вероятность этого равна, скажем, 0.0000000000001. Как было показано выше. Ну и что? Если вдруг совпадет — у второго участника торрент не захешируется, скажут — дубликат хэша, так что идите в жопу обратитесь к администрации трекера или разработчикам клиента.

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

Это ерунда.
ты сначала докажи возможность существования 2 _валидных_ торрентов с одинаковым хэшем. пока таковые не найдены.
Это мне ответ? я как раз считаю, что ситуаиця ерундовая. есть ли такие торренты, нет…
Верно. Поэтому и говорю, что info_hash вполне себе нормальный естественный ключ.
ваш пример про нерезидента немного притянут за уши, если мы изначально на них не рассчитываем то даже при наличии AIPK ИНН, ОГРН 100% будут NOT NULL UNIQUE, что все-равно дает проблемы потом, а если расчитываем на нерезидентов то и составной ключ будет какой-то другой.
Это не пример, а реальная БД с реальной ситуацией.

Из статьи мы видим:
У данных нет реального ключа. Очень плохая причина. Ее появление иллюстрирует как плохой дизайн базы данных в целом, таки и то, что разработчик на самом деле не понимает данных, с которыми работает.

Либо мне не везло, либо я правда не понимаю данных. Можно парочку примеров где в решении используют ключи, а можно без них? Будет отлично, если на open-source проекте.
Тов. sherbacov всё правильно сказал. На эти грабли рано или поздно наступают все. Раза после второго, как правило, приходит понимание, что практику не всегда можно стопроцентно положить на теорию. Так и возникает необходимость AIPK и денормализации.
Не совсем понятен ваш вопрос. Беркус имеет ввиду, что если по данным нельзя сказать, что делает данную запись уникальной, вы их не совсем понимаете. Это не означает, что ключей быть не должно.

Хотя, если подумать, то, например, в таблице постов форума какой ключ можно считать естественным?
Не совсем понятен ваш вопрос.

Когда у нас нет уникального значения (например IP адрес), он предлагает использовать ключ из набора реквизитов (ФИО + Паспорт+ Место рождения) и данное правило будет работать в большинстве случаев.

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

А по данной философии использование хешей в ключах еще хуже, т.к. даже в теории не обеспечивает уникальность и это просто попытка заменить суррогатные ключи
Где написано, что Беркус предлагает именно это?
Где написано, что Беркус предлагает именно это?

В статье под Вашим переводом

Компромисс с многоколоночными ключами
(ФИО + Паспорт+ Место рождения)

У данных нет реального ключа
А где в этой статье сказано про паспорт? Я что-то не понимаю.
Это просто пример много колоночного ключа.
Это только одна из возможных ситуаций. И не нужно ее обобщать на все остальные случаи. Да и пример ваш не подходит. ФИО + Паспорт+ Место рождения никак не может быть естественным ключом. Разве что (серия + номер) паспорта. Поскольку эти данные однозначно идентифицируют личность в нашей стране.

Кроме того, Беркус вовсе не говорит о том, что от суррогатных ключей нужно полностью отказаться. Он говорит, что злоупотребление ими приводит к проблемам.
Разве что (серия + номер) паспорта. Поскольку эти данные однозначно идентифицируют личность в нашей стране.

Паспорт меняется в течении жизни, фамилии и имена тоже, но личность при этом остается той же самой личностью, и должна идентифицироваться в базе однозначно.
Я не вижу ни одного не суррогатного варианта для ключа в таблице Clients
В данном случае в предметной области невозможна однозначная идентификация личности. Ей можно заменить органы, сделать пластику на лице. Даже мозг перепрограммировать и внушить, что она — Джон Кенеди, не говоря уже о липовых документах и отпечатках пальцев.

Почему нужно требовать, чтобы на модели эта идентификация была возможной, если в предметной области она невозможна?

Естественный ключ — понятие, тесно связанное с предметной областью, как мне кажется. И если в предметной области его найти не представляется возможным, то причем тут DBA?

Кстати, если мы говорим об однозначной идентификации личности, то в нашей стране ИНН присваивается один раз, если я не ошибаюсь. А в США — номер соцстрахования. Можно попробовать в естественные ключи их взять.
Вы меня не слышите.

1. Если есть УНИКАЛЬНОЕ ЗНАЧЕНИЕ ОНО И БУДЕТ КЛЮЧОМ. тут никто суррогатного ключа и не использует.

По данной статье (Компромисс с многоколоночными ключами):
2. Говорится, что если нет Уникального значения — используйте несколько вместо суррогатного ключа.
Я же утверждаю, что если у ВАС НЕТ уникального значения в одном реквизите, то существует вероятность дубликата и следовательно лучше использовать суррогатный ключ. И они не являются «устаревшими» или компромиссом.

Поэтому их НУЖНО использовать везде, где нет УНИКАЛЬНОГО ЗНАЧЕНИЯ.

НО, есть 2-3 % случаев, когда их нужно использовать:
-------------------------------------------------------------------------
 CLIENT_ACCOUNT     | CURRENCY | BALANCE
-------------------------------------------------------------------------
1                   | RUR      |     100.0
1                   | USD      |     100.0
1                   | EUR      |     100.0


В этом случае — да, суррогатный ключ будет ухудшать структуру таблиц и отсутствует вероятность нарушения уникальности CLIENT_ACCOUNT и CURRENCY

поэтому для 2-3% случаев заголовок «Автоинкрементные первичные ключи (суррогатные ключи) = зло?» звучит немного «громковато»

>ИНН присваивается один раз
К сожалению в нашей стране есть люди с 2-3 ИНН и более, т.к. ИНН содержит разряд кода ИФНС и ИФНС может забыть проверить его выдачу в другой ИФНС.
Мне кажется, вы уводите дискуссию в сторону. Она началась с того, что вы сказали
Когда у нас нет уникального значения (например IP адрес), он предлагает использовать ключ из набора реквизитов (ФИО + Паспорт+ Место рождения) и данное правило будет работать в большинстве случаев.

Я отметил, что Джош этого и не говорил. Да, действительно, он говорит о том, что если у вашей таблицы нет естественного ключа — то вы не знаете своих данных. Но надо понимать, что если такой ключ в принципе невозможен в предметной области, то данное утверждение («вы не знаете своих данных») не применимо и просто придется использовать суррогатный ключ. Что вы и подтверждаете, приводя все новые и новые примеры проблемы с идентификацией людей. Вот такая у меня аргументация. А заголовок статьи тут вообще ни при чем. Мы его не касались в дискуссии.
Теоритически можно сделать в виде: Username + timestamp c ниибической точностью. Или username + порядковый номер поста данного юзера. Скажем, 776-й.

Да, теоретически можно. Username + timestamp кажется мне более удачным кандидатом, чем порядковые номера, кстати :)
А мне нет. Включать дату, тем более мелкогранулярную, в натуральный ключ — это плохая практика. Очень. По ряду причин.
> Вообще время никогда не стоит использовать в качестве ключа.

А зачем в логах вообще абсолютно уникальный ключ?

> Точного времени на большинстве серверов нет

Значит, время надо получать из единого источника. Например, автоматически проставлять время прямо на сервере БД.
А зачем в логах вообще абсолютно уникальный ключ?

Низачем, черт побери :) Это учебный пример.
Попробую ответить за автора.
Подразумевалось, что нужно было использовать не datetime и отдельный ключ, а timestamp и брать в качестве ключа его + user_id. Но как правильно сказал sherbacov, ко времени в качестве ключа привязываться довольно рисковано.
А лично я для себя в таблице log вижу ещё одну ошибку — это IP'шники, хранящиеся текстом.
Простите меня за неосведомленность, но как еще можно хранить ip, кроме как в varchar?
Возникло много вопросов.
Кому это может понадобиться? Зачем в логах нечитаемые людьми данные? Зачем постоянно преобразовывать туда-сюда эти данные (например при просмотре логов)?

Кажется я что-то в чем-то не понимаю :)
Это вопрос производительности, дорогой друг, и только.
Очень частые выборки по IP и все такой прочее, INT конечно же будет быстрее. Если они действительно очень нагружают базу.

Если такой вопрос не стоит и не встанет (ли?) то храните хоть в TEXT виде. А вообще, если уж хотите хранить IP-адрес (v4) текстом, храните в CHAR(15), если остальные поля таблицы тоже имеют постоянную длину, это позволит ей работать режиме FIXED ROWS. Я говорю о MySQL.

Вообще-то, для многих баз данных вопрос производительности может вообще не стоять, так что проектирование БД, как это не печально — не всегда компроммис между удобством и скоростью, но все равно нужно помнить об этом.
А что означает «нечитаемые людьми данные»? Я четырехбайтовые целые тоже не сразу читаю из бинарного кода :)
Все равно ведь при отображении лога он преобразуется. Не все ли равно, сколько этих преобразований на строку?
Вообще-то ip-адрес это на самом деле int, который для человекочитаемости разбивается на 4 byte.
Теперь уже может быть уместно хранить IP шестибайтовым целым.
16-ти вы видимо хотели сказать
Если Вы про IPv6 то там 16 байт и к стати не всегда однозначное текстовое представление
Да, в общем, я бы не сказал, что это была настоящая ошибка. Просто размышления на тему о поиске ествественного ключа и взгляд на таблицу с другой стороны.
Автор мозги пудрит, он же сео постгре. Был бы сео другого, рассказывал бы другое))
Он, кстати, свою любимую Postgre ни разу не упоминает. Ну разве что намекает немного :)
Да, странно… Мне кажется в большинстве случаев польза от автоинкрементных pk очевидна… Ну бывает конечно делают без нужды, но это я не знаю на сколько надо плохо понимать что делаешь…
Hibernate все таблицы строит с такими ключами, т.е. получается что он весь пропитан невежеством?
Неправда ваша. Как сконфигурите, так и будет.
И вообще, при использовании ОРМ, autogenerated id вообще не стоит юзать, но уже по другим причинам, не охваченным статьей
Если вы юзаете long-running «business» transactions (LRT), простирающиеся на несколько system «db» transactions, то вам, скорее всего, захочется иметь batch insert сущностей по окончании LRT, и не раньше. В случае, когда id генерится БД, вы это (batch insert) сделать не можете, т.к. создание сущности требует заполнения её id, за коим приходится лезть в БД, что ломает саму идею отсоединенной LRT.
Для MS SQL, в котором нет генераторов a la sequence, как в Oracle, это вообще вырождается в обязательную вставку объекта в БД.

Поэтому в таких случаях есть смысл юзать application-generated id — по алгоритмам HiLow или Guid.Comb. Особенно хорошо это описано в блогах авторов Hibernate/NHibernate
В Oracle вообще нет автоинкрементных ключей, там есть просто ключи и отдельно последовательности, а уж что вставлять в PK — ваше дело.
PS
для меня вообще сомнителен смысл кляузы auto_increment в объявлении поля.
сомнителен, когда придуманы последовательности (sequences)
Лично мне очень не хватает чего-то вроде такого в описании столбца:

create table t (
  id int 
     autoincrement using sequence t#seq
     constraint t#pk primary key
  ...

А написание кучи тупых триггеров вида
create or replace trigger t#trg_br_i 
  before insert 
  on t 
  for each row
begin
  :new.id := t_seq.nextval;
end;

меня очень расстраивает.
Ну а если по делу, то автоинкремент — это просто еще один инструмент разработчика БД, который у нас есть. И, конечно же, им надо уметь правильно пользоваться. Бывают случаи, вот как автор описал — когда они совсем лишние, и не надо поддаваться давлению всех и вся вставлять их везде где попало.
Прочитав оригинал, мне кажется одна из основных мыслей не в том, чтобы избегать суррогатных ключей, везде, где это возможно, а в том, что суррогатный ключ — это не панацея, нельзя просто его добавить и забыть о простановке юников и других типов ключей.
а не будет ли выборка по username дольше выборки по маленькому иду?
Конечно будет. Только не всегда эта разница во времени актуальна.
если одну запись по ключу то не заметно, а вот при джойнах и сортировках очень даже.
Может я ошибаюсь, но вроде как не будет.
PK-индкс всё равно внутренне хранится одинаково независимо от типа и размера поля.
Разве нет?
Нет, конечно. Primary Key обычно никак не отличается по сути от любого другого уникального индекса.
Ваш ответ получился путанным.
Тезис: любой уникальный индекс не зависит от типа и размера исходного поля, то есть имеет то же внутреннее представление и эффективность.
Так? ))
Сорри, я не хотел никого путать :)
Просто вопрос прозвучал, как будто бы Primary key не зависит от типа поля и всегда занимает одно и то же число байт :)
Так верен ли приведённый выше тезис? ))
Ну :) PK хранится также, как и любой уникальный индекс. А индекс, в свою очередь, конечно, зависит от типа и размера исходного поля.
Я помню в холиварах на эту тему учавствовал лет 10 назад :-) Не успокоились еще :-)
А если у меня этот id ещё где то потом используется, благо он уникальный?
Да, действительно, зачем нам суррогатный ключ, когда клиенту можно вместо ID-услуги (autoincrement) давать следующий ключ:
shop.php?category=123&good=45342&store=52&country=RU

Действительно, ведь на конкретном складе в конкретной стране может быть только один товар с таким названием, да?

Любая БД — это индивидуальный подход. Это совершенно уникальный мир, который нельзя копировать из другого проекта или основываясь на другой взгляд. Всё индивидуально.
Полностью поддерживаю идею автора. Сам все больше и больше стал отходить от первичных ключей, ибо действительно — id часто не несет ничего в предметной области! В объектной модели это всегда воспринималось мной как «поле только для mysql». Самый частый кандидат на замену id у меня — url, например id бренда легко заменяет его url.
вот про урл ооочень спорное утверждение, вот если-б вы сказали что id заменяет название бренда, то можно было-бы понять… особенно тема ребрендинга получается раскрытой :) Goldstart XXX != LG XXX
AIPK id тем и удобен, что не несет абсолютно никакой информации предметной области. Это просто уникальный идентификатор объекта в некоем пространстве имен (таблице в нашем случае). И никакие изменения предметной области гарантированно на него не повлияют. Если вместо абстрактного числового ключа использовать сущность предметной области — рано или поздно будут ужасные грабли. У Орлова в «Записках автоматизатора» неплохой пассаж на эту тему.
Свойство уникальности ключа еще не является достаточным для того, чтобы связывать по нему данные с другими таблицами. Необходимо, чтобы значение связующего ключа никогда не менялось. И в этом случае инкрементальные идентификаторы подходят весьма кстати.
повторюсь — вовсе нет необходимости в том, чтобы «значение связующего ключа никогда не менялось» — обновлением ссылок при изменении поля внешнего ключа должен заниматься ON UPDATE CASCADE этого внешнего ключа. Другой вопрос, что его в 99% случаев игнорируют и в некоторых случаях может работать медленно
Мне кажется, такой цепочкой рассуждений можно, в принципе, прийти к тому, что как таковые идентификаторы не нужны и вовсе. Изменил человек имя — ON UPDATE CASCADE по всем таблицам? :)
Вы забываете о том, что во многих случаях не все использования идентификаторов объектов полностью под контролем СУБД, и у вас просто не получится изменить все ссылки на данный идентификатор, если он ушел за пределы СУБД. Например, если идентификатор используется в URLах и при связи с другими информационными системами.
Тогда уже этот идентификатор никак нельзя назвать «суррогатным»
Почему? Он так называется только потому, что он «суррогатный», т.е. не родной ключ на данных. Что такого в том, что его используют внешние системы?
В OLAP базах принцип построения таблиц несколько отличается от обычных OLTP баз. Наиболее популярное построение в форме звезды: в центре огромная фактовая таблица (хранит полную информацию о событии), к ней лучами соединяются более мелкие таблицы-справочники (содержат дополнительную информацию). Так вот, за использование суррогатных ключей бьют по рукам. В факте должны храниться осмысленные данные, а не бесполезные цифирки. А значит и в справочниках в качестве ключа выбираются реальные данные.

Казалось бы, суррогатные ключи позволят уменьшить объем данных: вместо повторения строки в 20-30 символов использовать 4-х байтный числовой ключ. При том, что в факте сотни миллионов строк, это существенная экономия места. Но в OLAP прежде всего важна производительность и бизнес-логика. Использование реальных ключей в большинстве случаев позволяет вообще избежать соединений со справочными таблицами. В качестве компромисса можно использовать популярные коды — они небольшого размера.

Приведу пример возможного факта. На каждое поле, имеющее KEY в названии, имеется справочник с информацией о полном названии на разных языках и т.п. Но и без справочника легко догадаться, какую информацию они обозначают.
-------------------------------------------------------------------------
 TIME_KEY | COUNTRY_KEY | REGION_KEY | USER_KEY | SEX | KARMA | HABRASILA
-------------------------------------------------------------------------
10.11.2010  RUS           VRN          maovrn        M     111        222
10.11.2010  RUS           XXX          FractalizeR   M     333        444
10.11.2010  RUS           SPB          olyapka       F     555        666
10.11.2010  USA           XXX          umputun       M     777        888


Для сравнения:
-------------------------------------------------------------------------
 TIME     | COUNTRY_ID | REGION_ID | USER_ID | SEX | KARMA | HABRASILA
-------------------------------------------------------------------------
10.11.2010  1           16          1234        1     111        222
10.11.2010  1           0           1432        1     333        444
10.11.2010  1           2           431         2     555        666
10.11.2010  66          0           111         1     777        888
Знаете, вы в комментарий небольшого размера уместили 100% понятное объяснение того, о чём статья. Спасибо вам, я наконец понял о чём сыр-бор :)
Это может и делает суррогатные ключи злом, но лишь для OLAP баз данных =) В обычной бд, напротив, тяжкие увечия можно получить за использование user_key/login/email вместо user_id
1. Вы привели не совсем удачный пример. Код страны — это просто академический пример того, когда лучше использовать естественный ключ (и использовать, кстати, лучше ISO 3166-1 Alpha2 или Numeric, но никак не Alpha3 в вашем примере, у него самая низкая эффективность).
2. Во-вторых, я бы убил того, кто вместо естественных первичников регионов, умещающихся в байт, закрепленных законодательно, будет использовать выдуманные самим алиасы вроде «VRN».
3. Поле USER_KEY — это еще один удар по производительности OLAP-приложений. Вы вообще понимаете, что соединение со справочными таблицами = падение производительности — это далеко не аксиома? Пояснять и считать IO-операции надо или сами догадаетесь, почему?
4. В таблицах должна находиться эффективно закодированная информация. И в зависимости от эффективности где-то используются естественные, а где-то суррогатные ключи. Только очень больной человек будет нуждаться в читаемой человеком информации для таблиц, как вы говорите, на «сотни миллионов строк». Если уж очень приспичило сделать ее user-friendly — напишите вьюху и читайте по ней, а ваш USER_KEY вместо USER_ID — это оверхед на объем, на IO-операции и скорость в целом, если поле индексируемое (не кластерный индекс), то оверхед на размер индекса и операции по нему. В общем за такое надо отрывать руки ;)
1. В принципе да, код страны можно безболезненно сократить до двух символов: RU, EN, FR и т.п.
2. Вы имеете в виду автомобильные коды? Не наглядно. А VRN, SPB не выдуманный алиас, а часто используемый.
3. и 4. Линейное чтение во-первых в большинстве случаев действительно быстрее соединения огромной таблицы со справочником. Конечно, надо подходить с умом и не стоит повторять из строки в строку здоровенный текст. Осмысленная информация упрощает логику => снижает риск ошибок. Поле USER_KEY уникально в пределах одной даты, таблицы фактов обычно секционируются по дате TIME_KEY, значит в пределах секции логин пользователя уникален и не повторяется. Избыточности информации нет. Мы вообще в своем проекте индексы практически не используем. Если надо обработать дневную порцию данных, проще прочитать всю дневную секцию и отсеять несколько лишних строк, чем соединяться с десятком справочников по индексу.
2. Они такие же автомобильные, как и коды ИНН (начинаются с кода региона), например ;) Это стандартный классификатор. А вот VRN-абсолютно выдуманный. Есть стандарт ISO 3166-2, там Воронежская область обозначена как RU-VOR, есть ГОСТ 7.67 — там тоже VOR или ВОР. Данные значения являются естественными ключами, а VRN — суррогатным ;)
3. Осмысленная информация должна подаваться пользователю через интерфейс, а внутри она должна быть, как я уже говорил, эффективно закодирована. Поставили Alpha3 вместо Alpha2 и на сотне миллионов записей получили 100метров лишней информации и больше 10000 лишних IO-операций на один полный скан. Не знаю, как вы работаете с большими таблицами фактов, но мы там деремся за каждый байт и индексы используем очень активно. Даже просто на подсистемах отчетности, которые работают с сотнями миллионов записей. А уж для OLAP-систем, когда время отклика по определению лимитировано до считанных секунд идет побитовая война :)
2. Ок. Будем считать что это только у нас «так исторически сложилось». Но коды вроде VRN используются повсеместно в рамках проекта и всеми приняты как естественные и логичные.
3. Теоретически так и есть, идет война за каждый байт. Но на практике чем придумывать как сжать данные (сделать суррогатный ключ = создать новую сущность и потом маяться с преобразованиями) проще в плане логики оставить ключ естественный, если он уникален и не слишком большой. В общем не стоит впадать в крайности.
Если интересно, могу показать насколько линейное чтение эффективнее прыганья по индексу. Надо не забывать, для чего используется таблица фактов. Для массовой обработки больших объемов данных. Информация в таких таблицах денормализована и это нормально. Если обратили внимание, поле SEX по-хорошему должно быть в справочнике пользователя, но оно вынесено в факт чтобы можно было посчитать, скажем, соотношение кармы мужчин и женщин, не соединяясь со справочником.
Запрос в духе select * from FACT where USER_KEY='maovrn'; для OLAP нонсенс. Никто так делать не будет!
Никто так делать не будет!

Особенно мне нравятся люди, которые заранее все про всех знают :)
Ну если кто-то так сделает, то просто не дождется результатов :-) Возможно даже его запрос будет прибит администраторами, а автор сего чуда получит выговор. Для оптимизации надо как минимум указать из какой секции читать данные. Это просто такие особенности хранилища, надо мыслить несколько иначе. Ведь никто в здравом уме не станет для отображения титульной страницы веб-сайта делать запрос, включающий сложную группировку по всей таблице. Аналогично никто в хранилище не станет искать одну или несколько строчек аля иголку в стоге сена.
Да интересно все, только пример достаточно странный. В данном случае карма, как раз, должна храниться в справочнике пользователей. И при подсчете данного соотношения таблица фактов использоваться не будет в принципе. Это, как раз, в случае OLAP-направленности. А вот в случае OLTP мы бы уже подумали. Опять же надо смотреть на соотношение количества пользователей и количества записей в факте.
Карма изменяется в зависимости от времени, это исторические данные. В OLAP она не может быть в справочнике. В факт строки только вставляются и почти никогда не апдейтятся, каждое изменение кармы пользователя — новая строка. По такому факту можно просчитать динамику изменения кармы, определить зависимость роста/снижения кармы от дня недели и т.п.
А вот в OLTP карма будет в справочнике и будет иметь только актуальное на текущий момент значение.
> Первая таблица… таблица логов.… Что делает конкретную строку таблицы уникальной? Ответ очень простой. Комбинация из ID пользователя и времени возникновения события.

Юзер не может за одну секунду выполнить несколько разных действий? Даже если это какой-то робот?

По моему, во всех списках сущностей надо юзать AIPK. Не нужен он лишь в таблице связей или ещё в каких-либо технических таблицах. Вот если AIPK начинают использовать в таблице связей — это да, жесть…
Разумеется, может. Поэтому я и говорю, что log_occured_on имело недостаточную разрешающую способность.
Заранее прошу прощения за оффтоп.
У вас в таблице есть поле ip varchar(15), у меня тоже по всем проектам есть такие поля. Значит ли это, что при переходе на ipv6 такие проекты отвалятся?
Кстати, как и те, кто хранят IP в BIGINT.
Черт. Чувствую запах денег :-)))
Я хранил в bigint и проблем с ipv6 не наблюдал. Правда сейчас перешел на binary(6).
Куда столько? Чтобы оставить резерв для IPv16?))
Ну, вообще-то адрес для IPv6 занимает 128 бит, т.е. 16 байт.
ru.wikipedia.org/wiki/IPv6

А не 6, как можно подумать, глядя на название.
Тьфу, голова моя дырявая. Говорю о IPv6, а в уме держу 48-разрядный MAC-адрес. Пора на пенсию)
В злоупотреблении суррогатными ключами.
Вот как раз таки это и не понял, что есть злоупотребление суррогатными ключами?
Ну, использование их тогда, когда есть вполне подходящий естественный ключ.
дело в том, что наличие ключа в одном формате позволяет писать единообразную логику доступа к данным. Т.е. например findById будет одинаков для всех энтити, или CRUD операции тоже просто генерятся подставлением полей и значений. А вот большого зла я так в глаза и не вижу.
А причем тут единообразная логика? То, что ваш CRUD-фреймворк не поддерживает составные первичные ключи или не позволяет с ними удобно единообразно работать — это проблема фреймворка, а не реляционной теории.
Проблема в том, что реляционная теория вынуждает меня подчиняться каким-никаким правилам, при обращении к ней через ее же api. Необходимость тягать с собой сложные ключи между слоями от юзера к базе, причем в каждом случае использовать различный набор ключей сильно усложняет задачу использования этого api. Так нафига себе придумывать проблемы и усложнять всю систему вцелом, если все можно сделать более менее единообразно избежав дублирования кода в фреймворке? Не забывайте, что реляционную теорию выдумывали бородатые дядьки, которые и в глаза не видели те системы, которые сейчас используются над ней.
Мне кажется, вы путаете понятия. У реляционной теории нет никакого API.

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

Но разработка ПО — это торговля. Продали немного быстродействия, получили красивый интерфейс. Чтобы купить себе дополнительную проверку уникальности в базе данных без потери быстродействия БД, можно попробовать пустить с молотка удобные, но глупые суррогатные ключи и простоту их реализации, а на вырученные деньги естественную форму данных. Кто может сказать, выгодна ли эта сделка? Только разработчик, после тщательного анализа.

И потом. Вы снова забыли слова, которые повторяются в статье. Опасно не использование, а злоупотребление. А вы снова пытаетесь оценивать ситуацию с позиции черное/белое.
Нет, не можете. Первый же экспорт/импорт разрушит всё нафиг.
Я не про все пункты вообще, я только про случай необходимой идентификации конкретной записи, иначе бы сиквенсы не придумывали ;)
На самом деле автоинкрементные id штука весьма удобная. Во-первых, поиск по числовому ключу обычно быстрее, чем по строке. Поэтому даже имея однозначно уникальный ключ-строку есть смысл пользоваться суррогатом для быстрого поиска. Во-вторых, такой идентификатор абстрактен. Он сам по себе не несет смысловой нагрузки, а значит нам гарантированно не придется его менять. Так что отказываться от таких ключей просто из принципа не стоит, благо оверхед у них минимален.
UFO just landed and posted this here
почему то никто не говорит о размере индексов, а он значительно увеличится при использовании не суррогатных ключей.
Автор говорит про маленькие бд, а в них часто обходятся вообще без ключей-триггеров.
То «добро», которое причинила Вам прочитанная статья, заключается не в том, что Вы осознали ненужность AIPK в некоторых из своих таблиц, а в том, что Вы, наконец-то, задумались над тем, какие же, собственно, данные лежат в базе, какие у этих данных особенности, и как это знание может помочь упростить и улучшить проект.

Это — очень правильно, думать о таких вещах надо, причём до создания таблиц. Другое дело, что, как показывает практика, в большинстве проектов никто об этом не думает, и им это «сходит с рук». Поэтому народ считает, что тратить на такие размышления время и напрягаться лишний раз смысла нет (а то ещё и мотивируют это необоснованным увеличением стоимости проекта и времени разработки, если так часто задумываться над тем, что ты делаешь :)).

Что до самих AIPK, то, как с любым инструментом, всё зависит от ситуации. Выше приводили отличный пример с OLAP, когда AIPK это явное зло. Но в абсолютном большинстве случаев наличие «лишнего» AIPK не наносит сколь-либо заметного вреда (если не считать того, что это психологически способствует быстрому механическому созданию таблиц без особого анализа и понимания своих данных), а то и приносит некоторую пользу.

Я много лет назад попробовал убрать все «лишние» AIPK. Поработав так с полгода-год, я их вернул обратно, и с тех пор всегда и везде создаю (ну, кроме случаев где они явно лишние вроде примера с OLAP). Причина проста — без них оказалось значительно менее удобно ручками работать с базой в консольном клиенте mysql… а рано или поздно в любом нетривиальном проекте возникает потребность ручками покопаться в базе.
Я не вчитался в оригинальную статью, но если доверить автору перевода, то как-то всё очень неоднозначно выглядит.

Многоколоночные ключи: масса софта их не поддерживает. Одно это ставит крест на борьбу с суррогатными ключами. Может они и зло, но такое же зло как ИНН.

У данных нет реального ключа: пример с логами автора убедительно показывает что бывают данные без ключа.
1)При разборе логов порядок событий крайне важен, и где-то этот порядок должен храниться. 2)Кроме суррогатного ключа кандидатов нет — две строки в логах могут быть вообще полностью одинаковыми, а знать о том что событие повторилось надо. Пример maovrn про OLTP: TIME_KEY + COUNTRY_KEY + REGION_KEY + USER_KEY. А если в данных они совпадут?

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

Смешаны причины использовать суррогатные ключи и автоинкрементные суррогатные ключи. Если их разделять, то логики в утверждениях об их вредности будет больше. Например, после вставки записи с автоинкрементным ключом трудно получить его значение — только mysql делает это быстро, так что вопрос о auto — отдельный уже по практическим соображениям. auto ключи проще в использовании и провоцирцют на ошибки — в этом и их зло, но это не вина ключей, так придётся объявить охоту на любой язык программирования без контроля типов.

Про хранение ip как строки или целого — строки будут неправильно сортироваться, целое нельзя посмотреть без инструментов. Есть и минусы и плюсы, разговор ниочём.

Проще смотреть на статью как на набор интересных разборов ошибок, а не как на аргументацию за или против ключей.

> Пример maovrn про OLTP… А если в данных они совпадут?
На самом деле данные в OLAP базу попадают из различных источников (OLTP баз, каких-нибудь логов). Пользовательский ввод хоть и встречается, но это скорее исключение. Прежде чем данные будут записаны в конечную таблицу (таблицу фактов или справочник), они проходят через этап ETL (Extracting Transformation Loading). Именно на этом этапе производится очистка данных, валидация, насыщение. Этот этап гарантирует, что данные в конечной таблице не совпадут. При этом в самой таблице нет primary key или unique constraint, т.к. данные уже чистые и дополнительные проверки будут только тормозить процесс.
Ага. Насыщение. Чем можно насытить две одинаковые строки, кроме суррогатных ключей?
Насыщение это то что входит в Transformation в аббревиатуре ETL. Что это такое проще объяснить на примере. Допустим у нас данные приходят из двух источников: логов апача и базы пользователей. Загружая информацию о количестве переходов по сайту того или иного пользователя (суммированная информация из логов), мы дополняем факт информацией из базы пользователей. В итоге получается факт, содержащий больше информации, чем содержит каждый из источников в отдельности.
Но, кстати, могут добавляться и суррогатные ключи, если без них обойтись нельзя. Объединяя данные из разных источников, описывающих одни и те же сущности с разных точек зрения и использующих каждые свои собственные ключи, ничего не остается другого, как завести свои суррогатные ключи и справочник, отображающий соответствия между всеми этими системами.
А ничего однозначного в мире не бывает. Я вообще не понимаю, что за подход последнее время на Хабре оценивать статьи, которые призваны задумываться с точки зрения Черное / Белое.
> только mysql делает это быстро

Разве? В каких СУБД получение идентификатора вставленной записи происходит медленно?
Можете привести факты/сравнения/бенчмарки? Это выглядит малоправдопобоным.
Например, я только что сравнил на postrges (через python и psycopg2) запросы вида «insert into users (name) values(?)» и «insert into users (name) values(?) returning user_id» — разницы не заметил. Пользовался sqlite и получал через sqlite_last_insert_rowid() — также не замечал тормозов.
AIPK
pro:
Они дают лишний слой абстракции — id есть id, и все тут. Любое изменение данных не ведет за собой изменение ключа, и т.д.

contra: они уникальны в рамках одной таблицы. Импорт нескольких связанных друг с другом записей из одной БД в другую — нетривиальная задача.
в книжках с картинками про БД написано, что нужно использовать первичные ключи с автоинкриментом везде. даже там где они не нужны.
"Как только эти проблемы будут решены, данная причина отпадет."
Вот когда отпадёт, тогда и можно говорить. А сейчас этот всё к чему? Т.е. — это костыль, но у нас рельсы кривые и костыль нужно выкинуть, а рельсы мы потом выпрямим. Ну-ну.
"У данных нет реального ключа. Очень плохая причина. Ее появление иллюстрирует как плохой дизайн базы данных в целом, таки и то, что разработчик на самом деле не понимает данных, с которыми работает."
Да ну? Теорию нарушает. А два одинаковых номера паспорта не хотите? Сам на выходных попал — кто-то где-то что-то в базе перепутал и у провайдера с моим паспортом два человека оказалось. Если бы у них не было бы первичного ключа — поля «USERID», это была бы знатная проблема. Т.к. фактически это был бы ключ к массе других таблиц. Это я к тому, что нет ничего плохого в добавлении некоторого уникального идентификатора. Есть у меня база людей. Можно номер документа использовать. А можно ввести искусственный номер пользователя. Страшный грех с точки зрения теории, но огромное благо с практической точки зрения. Более того вполне логично уникальной сущности назначить уникальный идентификатор. Даже если кажется, что у сущности уже есть естественный уникальный ключ, то это ничего не значит. Этот ключ — из внешнего мира, он не входит в систему моей базы. Сущность базы не есть настоящая сущность из реального мира. Она создаётся искусственно внутри базы и в некоторых случаях вполне логично создать для искусственный же идентификатор. Этого теория не учитывает. Все теоретики идут лесом — пусть попробуют свою теорию на действительно больших и сложных базах применить в голом виде.
Согласованность данных. Обычно убедительна. Но только в том случае, если вы действительно скрупулезно следуете плану и весь ваш дизайн тщательно спланирован.
Что за бред с точки зрения логики. Т.е. получается: это использовать можно, но в хорошо организованной базе. Т.е. предполагается, что использовать нельзя в силу того, что разработчик изначально делает плохую базу.
"Возможность легкого изменения. Неясно. " И что не ясного? Если полноценное каскадное изменение не доступно, то другого выхода нет. Даже если доступно, то нужно смотреть на структуру базы.
"Производительность. Обычно плохая причина." Ага, а потом начинаются слёзы и сопли «почему всё так тормозит». И идёт нагромождение костылей. А всё потому, что изначально кто-то не подумал о производительности.
Короче говоря, даже если банально читать, то получается, что автора противоречит сам себе. Большинство аргументов при детальном рассмотрении или субъективны или вообще свидетельствуют в пользу применение искусственного ключа. А основной аргумент — это плохо, потому, что плохо и ересь. Ну-ну.
«Как только эти проблемы будут решены, данная причина отпадет.»
Вот когда отпадёт, тогда и можно говорить. А сейчас этот всё к чему? Т.е. — это костыль, но у нас рельсы кривые и костыль нужно выкинуть, а рельсы мы потом выпрямим. Ну-ну.

Проблема может быть решена завтра в новой революционной СУБД. А может, она уже в какой-то СУБД решена.

Да ну? Теорию нарушает. А два одинаковых номера паспорта не хотите?

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

«Возможность легкого изменения. Неясно. » И что не ясного? Если полноценное каскадное изменение не доступно, то другого выхода нет. Даже если доступно, то нужно смотреть на структуру базы.

Совершенно верно. Потому и неясно, что на структуру надо смотреть.

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

C какой стати это предполагается? Мне кажется, вы запутались в логике.

«Производительность. Обычно плохая причина.» Ага, а потом начинаются слёзы и сопли «почему всё так тормозит».

Про вред преждевременной оптимизации уже говорено-переговорено миллион раз.

А в целом мне понравилось, что вы считаете себя уменее Джоша. Так держать! :)
Поддерживаю!

от себя — никто не строит базы из соображений, чтобы она лучше соответствовала стандарту ANSI SQL, принципам Кодда и каким-то положениям реляционной алгебры.

Строят схемы, которые удобны, компактны, производительны (в некотором нужном балансе). И все.
В борьбе добра со злов все равно побеждает бабло :)

Не надо напрягаться по поводу AIPK. Я лично создаю таблицы под сущности. Если надо foreign key то начинаю думать про первичный индекс. Если надо уникальность — делаю свой индекс. Уже после, в качестве оптимизации, можно добавить индексы индексы или даже добавить пресловутый AIPK. Оптимизация, к стати, может здорово перетряхнуть всю структуру базы.

В общем лениться надо в меру. И избегать шаблонного мышления.
И все-таки, что эффективнее: суррогатный ключ или составной по n-полям?
Этот мир не делится на Черное и Белое :) Надо смотреть применительно к ситуации. Чего даром воздух сотрясать?
Спор теоретиков с практиками.

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

Без искусственного ключа не обойтись, даже если этот ключ не соответствует ГОСТу.
UFO just landed and posted this here
Я с вами согласен. Поэтому я не один раз просил не обращать внимание на подобные вещи. Это старый проект, он разрабатывался в гм… особых условиях.
UFO just landed and posted this here
UFO just landed and posted this here
Спасибо большое за статью и ссылку на Селко.
Sign up to leave a comment.

Articles