Как стать автором
Обновить

Комментарии 98

Простите, но оформление статьи лютая жесть...

Полностью согласен! Крутил исходник и так, и эдак - всё равно кроме двух абзацев и картинки в голову ничего не пришло, поэтому кто осилит до конца сею пиСсанину имеет право на шоколадную медальку!

Выделение абзацев Вам бы помогло. Куплю себе медальку, обязательно шоколадную

выделил абзацы

А я считаю, что оформлено как надо - упор на юмор. Здесь не надо ничего структурировать - это так, "лёгкое чтение". Мне понравилось - сразу вспоминаются аналогичные

Не-не-не, к юмору определённо претензий нет и быть не может. В этом смысле статья на 5+.

Коллега, вероятно, имеет в виду абзацы, пунктуацию. Но с этим лучше бороться через ctrl+Enter, конечно же.

сделал легкий тюнинг текста

Мы же на Хабре — рефакторинг!

Совершенно обычная ситуация, бардак обыкновенный

Вы странных архитектур не видели, если вас инты в строках и таблицы без индексов до сих пор удивляют.

Давно не удивляют ?‍♂️

Слишком быстрый happy-end! ?Не хватает части как искали собственников данных, как согласовывали изменения, как ИБ не давало доступ и так далее... ?

С доступами было наоборот хорошо :) как и с ИБ, что потом в итоге организации вышло боком

Доступы и ИБ обычно в противофазе - если с доступами хорошо, то значит с ИБ плохо и наоборот. ?

Примерно так и было

И ещё подробностей, как в процессе исправления нашли критический баг приводящий к некорректной логике, а потом выяснилось, что на этот баг уже сделали костылей и его исправление ломает всё

Это ещё одна обязательная вишенка на таком торте!

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

Вспомнился високосный 1900-й...

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

А при чем тут ACID?

Извините, acid за уши притянут, тут скорее нарушение 2нф и атомарности

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

Даже 1нф и 2нф?

согласен, с первой нф погорячился, её нарушения редко видно. А вторую только так нарушают, особенно в big data.

Так НФ - это вобщем-то не требование/правило, чтобы ее нарушать. Это стремление минимизировать таблицы с точки зрения оптимизации хранения. На практике довольно часто приходится этим принебрегать в угоду скорости выборки, в этом нет проблемы.

Ну не только оптимизация хранения, но еще и консистентность. Если одну копию изменить, а вторую - забыть, то что потом делать и как искать правду?

Проапдейтить ту, которую забыли данными из той, которую не забыли.

Как определить, которую именно забыли. Вот что правильно: 13 или 17?

В любой непонятной ситуации правильно будет 42.

Храните номер версии или дату последнего обновления :)

Как определить, которую именно забыли. Вот что правильно: 13 или 17?

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

Юзер Ваня через окошко "Контрагенты" обновил адрес ООО "Рога и Копыта", юзер Петя тоже обновил адрес ООО "Рога и копыта" но уже через окошко "Контакты". Оказалось что два этих окошка работают с разными таблицами. Для скорости, да. Записи в таблицах теперь почему-то разные. Какие данные теперь правильные?

Усложняем задачу: это было полтора года назад, Ваня и Петя уже уволились, кроме "Рога и Копыта" у вас еще две сотни контрагентов.

Открываете хисторную таблицу, и смотрите дату последнего обновления.

Так надо не забывать) Но вообще, на моей практике в таких кейсах такие данные меняются чуть реже, чем никогда.

1нф отсутствует как класс во всевозможных document db. В бигдате чаще всего отсутствует если база данных поддерживает repeated field.

Ох, у меня коллега кодил в 90х похоже - одной непрерывной строкой. :)

Да я так до сих пор код пишу, его мало кто после меня видит

Нещадно плюсую - нечего коллегам расслабляться.

была непонятна первопричина, заставившая Чичикова мотаться по России. Это уже потом мне объяснили, что причина была в грядущем освобождении крестьян от крепостного права и похожа на схему с возвратом НДС через левую контору,

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

Что за эротические фантазии. Хотел взять кредит под залог крестьян и пропасть. Инспектору, которые приедет проверять наличие душ, дать на лапу.

Не знаю, не знаю. Лично мне помнится так. Может быть, потому, что в советское время было бы довольно сложно объяснить (да ещё школоло), что такое "кредит", да ещё под залог.

Это при встрече с Ноздрёвым Чичиков историю историю про свадьбу придумал:
— Ну, так я ж тебе скажу прямее, — сказал он, поправившись, — только, пожалуйста, не проговорись никому. Я задумал жениться; но нужно тебе знать, что отец и мать невесты преамбиционные люди. Такая, право, комиссия: не рад, что связался, хотят непременно, чтобы у жениха было никак не меньше трехсот душ, а так как у меня целых почти полутораста крестьян недостает...
— Ну врешь! врешь! — закричал опять Ноздрев.

А поскольку это самое первое объяснение (хоть и придуманное на ходу) которое встречается в книге, вот оно и осталось в памяти. А настоящая причина скупки мертвых душ раскрывалась в последней главе :

"Эх я Аким-простота, — сказал он сам в себе, — ищу рукавиц, а обе за поясом! Да накупи я всех этих, которые вымерли, пока еще не подавали новых ревизских сказок, приобрети их, положим, тысячу, да, положим, опекунский совет даст по двести рублей на душу: вот уж двести тысяч капиталу!...."

Ну а зачем ему деньги-то? Да, в том числе, чтобы женится на хорошей невесте. Почему по вашему во времена Пушкина мужчины женились в основном в 30+ лет, а женщины могли вообще в 15 лет выйти замуж? Именно поэтому, от мужчины ожидали, что он будет полностью содержать семью, а женщина просто будет рожать детей.

Деньги ему для того чтобы жить хорошо. Хорошая невеста сюда, может, и входит (а может и нет) — но вот никакие родители никакого условия на количество "душ" ему совершенно точно не ставили.

Возможно

Ниже комментарий верен. Мне в свое время учитель объяснял так. Перепись крестьян проводилась не чаще 1 раза в 10 лет. В этот промежуток они считались живыми по "ревизским сказкам". Чичиков хотел заложить несуществующих крестьян и получить под это дело кругленькую сумму. Когда все это выплыло бы - крестьяне оказались умершими и формально к Чичикову претензий бы не было.

Помню, как-то работал с системой, в которой было 3-5 (уже точно не помню) способов представить булевый тип данных в базе, и ни один из них не был нормальным. Запомнился только мой фаворит: varchar(1), где символ '1' – это true, а null – это false.

Ещё там в качестве "языка разметки" при формировании документов использовался Lisp, интерпретатор которого был зашит в Java (система была на Java).

Помню, как-то работал с системой, в которой было 3-5 (уже точно не помню) способов

В конфигах линуксовых оно и сейчас так.
Хорошо ещё, если не THIS_CRAZY_VALUE_IS_TRUE как "истина", любое другое - "ложь".

Иванов *
Иванов *
Иванов *
Иванов Пётр *
Иванов Пётр *
Иванов Пётр Сидорович
Иванов Пётр Геннадьевич

Такое... пишет в поле имён гостей одна достаточно известная ERP. Почему и зачем - загадка.

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

Я жажду подробностей. Какого рода ошибка? Какие ещё ошибки были (ибо один багфикс не мог бы сломать работоспособность всей системы)? Как оно вообще работало?

НЛО прилетело и опубликовало эту надпись здесь

ой, да я целые куски кода иногда внедряю через какой-то то if и проверку feature flag, а потом перед окончательным внедрением некоторое время остается

if(true){...}

Очень странный фикс, конечно сломалось, т..к. логика поменялась. Вместо присваивания, поставили проверку. Разбираться конечно надо, что имелось ввиду.

Мне встречались такие записи. И в моем случае их надо было фиксить типа так:

$var = true;

if ($var) {

Под true - там может быть и переменная и функция.

Вас не смущает, что if ($var = true) это как бы и не проверка вовсе? Тело этого if'a будет выполняться всегда. Если вы уберете if, то в логике, собственно, ничего не изменится.

А там перед этим define('true', 0), кек.

Потому, что данные приходят из других источников и придти может что угодно и когда угодно. Например, строка вместо числового идентификатора.

Это в стиле хуяк-хуяк и впрод?

НЛО прилетело и опубликовало эту надпись здесь

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

Потому что ID не является числом. Это идентификатор. Арифметические операции с ним бессмыссленны.

Очень напоминает логику одной системы для хранения, скажем так, сущностей клиентов в одном очень большом зеленоватом банке, название которой начинается на "Е" и состоит из трёх букв )

Прилететь действительно может что угодно и откуда угодно, от ФНС до планшета операциониста, поэтому абсолютно все поля - string, и только внутренние идентификаторы самой системы long int.

Просто одно дело когда такое делают в программном коде на языках программирования для быстрой разработки без строгой типизации, а другое дело когда закладывают бомбу в структуре СУБД (в которой целостность данных как минимум должна быть, констрейнты и много другое) . Разные уровни последствий (исправить код против исправить структуру СУБД) . Да автор умный - разгреб , а они все ...

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

Ну вот возьмём, например, api для интеграции от Авито. Они присылают сообщение на вебхук 1 раз, если его не суметь обработать — эту информацию уже не достать (потому что у них id пользователей в вебхуках и в api разные!). Ах да, они ещё и активно дорабатывают своё api, меняя схемы без предупреждения (а данные не всегда этим схемам соответствуют).


Ну и что в этих условиях вы напроектируете, если интеграция важна?

В такой ситуации вам СУБД вообще не нужна. Обработку вебхука можно свести к простой операции: сложить весь ответ в очередь. Разбирая ответ по полям и кладя его в БД вы натягиваете сову на глобус.

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

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

Какие вебхуки? Какой api? И авито тут к чему? Это обмен данными между двумя монолитами в одной организации, не я придумал использовать шину для обмена, моя задача решить проблемы с бд. Тут не перекладывание json из внешней системы в свою.

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


Только вот кому-то её придётся обслуживать, и у этого "кого-то" может быть своё мнение насчёт того будет ли он устанавливать и обслуживать Кафку. Поэтому костыли в СУБД вечны.

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

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

Ну нет.

Есть такие авторы которые начинают писать текст без каких-то вводных частей, сплошным потоком мыслей персонажа. Читатель в такой момент выдает автору некий кредит доверия, надеясь что через не слишком продолжительное время все ниточки завяжутся в узелки и будет понятно ради чего это всё. И в конце читатель скажет: "Эвон как! Ого! А я-то и не думал..." . Что имеем здесь. Автор решил типовую проблему для БД - наличие дублей. Автор молодец. Всё. И об этом статья?

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

Вот представь, что тебе доверили достроить за другим прорабом лабораторию на острове. Ты приходишь на объект, а там кроме недостроенного здания: огромный вентилятор (размером со здание), большой воздушный шар и комната набитая швабрами. Почесав голову, ты разбираешь этот хлам и доделываешь лабораторию. Сдаешь объект ученым, но через 5 минут они выбегают с криком: "УТЕЧКА ЯДОВИТОГО ГАЗА!!!".
— Как так–то, блять! Должно же работать! — в отчаянии кричишь ты и звонишь прошлому прорабу:
— Вася, у нас ядовитый газ потёк! В чем проблема?
— Не знаю, должно было все работать. Что–то в проекте менял?
— Немного, швабры вынес...
— Швабры потолок держали!
— Что??? Что, блять, извините???
— Говорю, швабры потолок держали. Над ними цистерны с газом были. Очень тяжелые, пришлось в комнату снизу швабры напихать.
— Ты хотя бы записку на двери повесил бы, что швабры для держания потолка! У нас тут ядовитый газ течет! Что нам делать?
— Включай вентилятор. Он сдует газ с острова.
— Я его, блять, демонтировал сразу же!
— Зачем?
— Зачем ты построил 120 тонный вентилятор? Ты не мог положить ящик блядских ПРОТИВОГАЗОВ?
— Ящик противогазов искать нужно, а вентилятор у меня с прошлого заказа оставался.
— Вася, я убрал твой вентилятор! Мы тут задыхаемся!
— Херли вы тогда там делаете? Садитесь на воздушный шар и уебывайте!

в начале 90х работал в конторе. Язык ДИАМС (mumps). И в отделе было 3 основных программиста. Поскольку я переквалифицировался из электронщика в программисты, приходилось иногда работать с чужим кодом.
Один вроде писал нормально. Но остальных двух запомнил навсегда:
1 - именовал переменные только как A2, B5, C31 и так далее. Переменных было много. После страницы текста было уже невозможно вспомнить, зачем нужна переменная D4.
2 - использовал динамический код. Хранил в базе куски кода, которые подгружались по условиям, после чего формировался какой-то код в переменных, переменные выполнялись по execute. По коду было невозможно понять, что происходит в программе, приходилось понимать только через отладчик.

Сюда бы копирайт...

Кул стори, бро ;) Выглядит как тайм-бомба. А такие вещи делают не от неумелости, а для подстраховки от кидка. Судя по всему, кидок произошел

Не думаю, просто неумелость разработчиков

Неумелость? Не думаю! (ц)

Заложить переполнение в правильное место, чтобы оно свалилось, но не не сразу. это надо умеючи. И чтобы DBA, даже просматривая содержимое таблиц, ничего не заподозрил. Да, и в результате срабатывания всё остановилось, и заказчик потерял денег. Напоминает поделки выетконговских партизан - выглядят коряво, но результат ровно как планировался.

Можно было начать класть туда \t!

"Случаи они разные бывают" (c) анекдот. Начинающие финтех разрабы делают счета как decimal, а потом "внезапно" появляются счета металлов.

Интересно. А как правильно тогда делать? Ведь float для хранения денег нельзя. В тексте хранить и свои обработчики делать?

int же. Хранить наименьшую единицу: копейки, центы, граммы, караты, планковские массы.

А в чем подвох с металлами?

а как быть с полями ID,PID,GID,SID? Где в varchar хранится целочисленные значения? Вообще все поля в таблице, кроме дат, имеют тип varchar(50) и varchar(100), удивительная согласованность.

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

Давайте переместимся назад во времени - в точку одной из многочисленных переинтеграций. Откуда то из-вне приходят xml-файлы. Айдишники там в то время возможно были символьными и только в одной из следующих интеграций стали целочисленными. Или в то время не было четко понятно или не было гарантий, что айди будут абсолютно всегда целочисленными. Но даже если при очередной интеграции было строго определено (с гарантией), что айдишники далее будут только целочисленными, то... возникает вопрос: "А стоит ли трогать работающую систему?"

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

Давайте переместимся назад во времени ...

В реляционных базах данных (наверное, в базах данных, вообще) с давних времён существует понятие домена — некоторого семантического диапазона допустимых значений. По идее, схема БД должна опираться на домены.

... Далеко не всегда второй вариант возможен и целесообразен.

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

Домен помогает когда задача обеспечения формата данных важнее задачи их сохранения. Если задача системы — хранить все поступающие в неё данные независимо от изменений в их формате, то тут не то что varchar, тут BLOB бывает хранить приходится.


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

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

Дальше упоминаются объемы данных — 20 тысяч, 75 тысяч записей — это по современным меркам вообще ничто, оно бы целиком лежало в дисковом кэше, и даже полный скан выполнялся бы за миллисекунды. Неочевидно, почему с таким объемом оно бы еле ворочалось.

Или это какая-то совсем специфичная БД, которую пора закапывать, но не дают.

75 тысяч строк, из которых 15 тысяч дублей, от 2 до 10 копий одной строки... Что будет индекс, что не будет, ворочаться это будет очень долго.

Тут индекс нужен для ограничения добавления дубликатов записи, по скорости проблема возникла из-за частого обновления данных и ненужного перебора одинаковых строк. 75к строк в одной таблице, а таких таблиц было достаточно, что запуск обмена данными накладывался друг на друга.

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

>Откуда взялись в таблице повторные записи о крестьянах сотрудниках?

Можно было и не зачеркивать

Спасибо!

В ВК, месте встречи "лучших", на всех проектах, что я работал, а они были буквально в несколько месяцев отроду, были точно такие же проблемы

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

Красиво, люблю истории с хорошим концом

А мне понравился текст)) Сразу вспомнилась ситуация, когда в СХД грузили данные из 1C в файловом виде txt раскладывая по таблицам. Вот тогда-то я и хапнула горя с того, что аналитик не хотел разбираться в табельных номерах (уникальный идентификатор каждого сотрудника внутри компании. Такой код можно в бумажной трудовой книжке найти) и положил их в number. А number просто взял и резанул лидирующие нули. И каково было «удивление», что появились дубли, которых на источнике нет и быть не может, потому что это зашито в системе. В общем как итог был полный транкейт с новой инициализирующей загрузкой. Самое прикольное, что выше по СХД (в витринах) эти number переводили обратно в varchar, потому что с другими таблицами не соединялось…?

Спасибо ☺️

А не офигели ли кадровики присваивать сотрудникам табельные номера, различающиеся только ведущими нулями?


Оно, конечно, понятно что varchar надёжнее, но вот табельный номер вообще-то является номером, то есть числом...

Согласно спецификации 1С в табельном номере могут присутствовать буквы. Так как источники редко уведомляют о таких изменениях в отдел КХД, то лучше опираться на спецификацию источника данных и его возможных значениях))

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории