Ограничения в базах данных считаются вредными?

В реляционных базах данных принято создавать ограничения для блокировки данных и их связи с другими таблицами. Так, таблица Users может иметь столбец email, который помечен как уникальный, потому что у каждого есть свой собственный email, верно? А таблица Subscription получает ненулевую колонку User, потому что каждая подписка должна быть связана с пользователем. Да, это тоже звучит разумно.

Но я здесь, чтобы поспорить против ограничений! Для кого-то это может показаться еретическим (или, по крайней мере, очень глупым), но выслушайте меня:

Мы используем ограничения по двум причинам: Для производительности (гораздо быстрее искать в столбце с уникальной индексацией), и для гарантии целостности данных (чтобы мы физически не могли ввести недействительные данные, например, бизнес требует, чтобы подписка была привязана к пользователю).

Вот в чем проблема: мы, программисты, часто оптимизируем слишком рано, и SQL-ограничения на самом деле не выражают бизнес-требования!

Позвольте мне немного разложить это по полочкам:

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

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

  • Ограничения, обеспечивающие целостность данных, действительно сталкиваются с проблемой неспособности реально отразить все требования бизнеса. Я имею в виду, что теоретически ограничения базы данных могут полностью выразить любое бизнес-требование, потому что, например, диалект PostgreSQL является полным по Тьюрингу, но это было бы безумием! Мы не программируем на SQL, мы программируем на C#, Python, Javascript и т.д. Реальная бизнес-функциональность должна быть реализована в наших языках общего назначения, а не в языке хранения данных. Так какие же ограничения мы должны вводить в базу данных?

    Я предлагаю вообще не вводить никаких бизнес-ограничений. Это звучит как безумный лай? Чем больше я работаю с SQL, тем больше меня умиляют полунадуманные «бизнес-ограничения», которые практически дублируют то, с чем уже справляется код. Что нам дает пометка столбца Subscription User как non-nullable, когда код уже гарантирует, что Subscription создается только по отношению к User? Это вообще не поможет, потому что ограничения просто не являются фактическим источником истины.

    «Но подождите», — слышу я протест некоторых, — «это же так просто — добавить non-nullable в колонку User«. Да, но это все равно вредит, потому что в основе своей не является источником истины для бизнес-требования.

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

  • Сложнее тестировать, потому что для тестирования Subscription нам теперь нужно также создать User и правильно их связать. Даже если тест не имеет никакого отношения к сущности User, ее необходимо создать. А потом представьте себе еще несколько сущностей, которые нужно правильно собрать вместе, чтобы создать Subscription, и работа с ними быстро становится очень мучительной! Затем мы можем начать прятать всю эту тестовую сложность в фабриках сущностей, но это просто абстракции поверх сложности, которую мы сами себе создали. Почему бы не избавиться от сложности полностью?

  • И еще сложнее адаптироваться, потому что введение новых возможностей в конечном итоге требует тщательной миграции, чтобы ограничения были синхронизированы с кодом: Что если мы действительно можем иметь подписки без пользователя? Что если столбец электронной почты не обязательно должен быть уникальным? Если слой хранения данных накладывает искусственные ограничения, это замедляет быстрое экспериментирование с такими идеями.

Я думаю, что многие из нас создают ограничения, потому что нас учили и/или говорили так делать. Но никто из нас в реальности не реализует 100% бизнес-правил на SQL, так где же провести черту? Ограничения, конечно, хороши, когда они дают реальные, ощутимые преимущества в производительности, но что произойдет, если мы ослабим систему, позволив этим сущностям быть более податливыми, с ними легче работать и тестировать?

В конце концов, только вы знаете свою область, поэтому нет общих ответов на мои утверждения. Однако я пытаюсь понять, что в проектирование реляционных хранилищ прокралась определенная догма, когда считается, что мы должны создавать ограничения, которые звучат совместимо с бизнес-логикой, потому что так принято. Вместо этого я предлагаю добавлять ограничение ТОЛЬКО там и тогда, где и когда это действительно и доказательно необходимо. Таким образом, базам данных будет позволено сосредоточиться только на хранении и извлечении данных, в чем они действительно преуспевают.

Фото Sam Moqadam on Unsplash

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *