Может это не обосновано, но вообще объедение бизнес логики и БД в одном флаконе что-то мне напоминает… была в своё такая популярная коммерческая система MUMPS кажется называлась… Тоже быстро работала, только когда проекты разрастались люди начинали плакать кровавыми слезами… Но скорее всего в этом проекте уже сделаны соотвествующие вывода из прошлого?
История показательна прежде всего тем что производители популярных браузеров могут при желании удавить любую компанию имеющую представительство в сети Интернет и ведущую бизнес в Интернет, просто потому что они большие и могут себе это позволить.
Таймзона это безусловно дополнительная информация ко времени события. Но описанный случай со временем прихода на работу является практически исключительным, и в этом случае я бы даже хранил таймзону как отдельное поле ) чтобы всем было понятно что эта информация которую нельзя потерять при всяких конвертациях ) Но если вам необходимо просто абсолютное время произошедшего события то таймзона лишняя информация которой просто не должно быть на уровне БД.
Используя принцип Оккама не умножать сущности без необходимости )
Вывод времени события в таймзоне пользователя относится к презентационной логике и конвертация в локальное время пользователя по моему скромному времени должна быть только там а не в хранимых процедурах и не в каком либо t-sql.
То же самое относится к загрузкам данных, у разных источников данных могут быть разные соглашения о формате времени и таймзоне, но задачу конвертации в один общий формат и одну таймзону БД лучше решать именно там в каждом конкретном сервисе загрузки данных.
Кстати таймзона БД не обязательно должна быть UTC, иногда удобнее хранить данные в таймзоне локальной для основной команды разработки. Но главное чтобы к этой таймзоне не применялись правила DST. То есть если EST так уж EST никаких там ESD.
На самом деле proc_open() тоже работает через системный вызов fork() в UNIX нет способа создать дочерний процесс без этого вызова. Все остальные варианты это просто обертки вокруг fork()/exec().
Но все равно на мой взгляд прекрасное решение в описанных условиях, что бы не говорили об этом другие коллеги )
Кажется примерно такие же идеи впервые высказывались при появлении pl/1 примерно в 70х годах прошлого столетия. Потом при появлении идеи CASE систем и чуть позже при возникновении RAD двадцать лет назад.
Насколько я понимаю, не важно что эти хэши означают для аналитика человека. Важно что они означают с точки зрения обучаемой нейронной сети, и сможет ли она предсказать уход клиентов после обучения тестовым набором данных.
Я не согласен с этим утверждением. Hint: IBM создавал свой PC точно не для домашнего использования, для этого эти устройства были слишком дорогими — $8-10k
Но это все не так важно. Важно что нужно с чего-то начинать. И в данном случае было проще начать с корпоративного рынка.
Добро пожаловать в Xcode с поддержкой языка Swift ) судя по примерам из Wikipedia Apple очень много позаимствовал из Rust для своего нового языка… чуть ли не все основные идеи. Так что вам должно понравится.
big data сейчас в тренде многие компании строят hadoop кластеры прямо сейчас.
А как учил нас Джаэл Спольски, чтобы иметь успех в массовом сегменте нужно чтобы твой процессор умел запускать Word и Excel.
Но даже это сейчас не гарантирует удачи, как показал пример Surface RT на ARM-е. Оказывается пользователи хотят чтобы работали все все сотни тысяч и даже миллионы существующих приложений к которым они привыкли.
А чтобы hadoop кластеры заработали на Power8 нужно всего лишь портировать Linux и Java.
Если удаться распространить технологию на энтерпрайзные кластеры со временем будет портироваться больше софта и возможно и массовый сегмент подтянется.
Сорри коллеги. Мне не нравится код ни до ни после исправления (
Конечно я может быть не понимаю всех нюансов кодирования на уровне ядра, но все же… функция очень длинная, я бы разделили ее на три по одной для каждого из поддерживаемых значений ThreadInformationClass и вызывал их из NtUserSetInformationThread.
Кроме того я бы перенес вызов UserEnterExclusive() туда где он действительно необходим, во всяком случае после проверки аргументов, которые наверняка можно проверять без эксклюзивного режима.
ThreadHandle используется не во всех кейсах switch-а, я бы делал вызов ObReferenceObjectByHandle(ThreadHandle, ...) только по необходимости и только для тех ThreadInformationClass для которых он действительно нужен, и опять же после проверки аргументов.
Зачем захватывать ресурсы которые не нужны?
Сообщение ERR(«Shutdown initiated\n») на самом деле не всегда будет говорить правду. Потому что если аргументы не пройдут проверку UserInitiateShutdown() не будет вызван и соотвественно сообщение Shutdown initiated в логах будет говорить не правду.
Кейс когда нужно проверить указатель на возможность чтения или записи и вернуть NTSTATUS наверное не единственный. Для этого можно иметь одну inline функцию или макрос которая(ый) будет использоваться везде.
И эта функция не единственная где есть похожие проблемы (
Можете мне сказать что предлагаемые изменения сделают код более длинным, добавят в стек исполнения еще один вызов функции что негативно повлияет на производительность. Это все правда. Но они точно улучшат читабельность и понятность кода что приведет к повышению безопасности.
Трудно залезть в чужую голову, но возможно у предидущего разработчика были на это причины совершенно невредоносного характера. Например — требования к производительности или функциональности. Например пользователи могут сохранить свои фильтры которые нужно применять автоматически в background-е, и он не смог придумать решения лучше…
Но так или иначе если вы видите сейчас более правильное / красивое / эффективное решение скорее всего это можно исправить.
T-SQL хранящийся в таблицах в БД, если я правильно понял суть проблемы, не отличается от хранимых процедур, его тоже можно переписать изменив подход, разве нет?
Если вернутся к dynamic SQL — то его главный недостаток в SQL Server в том что он забивает квери кэш который становится большим и теряет эффективность. (В MariaDb такой проблемы нет по той причине, что query cache там лучше даже не включать :)
Наверное это достойно отдельной статьи. Но если совсем кратко то полуавтоматически )
Что касается конвертации процедур то подход был такой:
Был powershell скрипт для предварительной подготовки текста, с теми заменами которые можно сделать с помощью regexp, например типы данных XML->LONGTEXT,UNIQUEIDENTIFIER->BINARY(16), и т.д., эквивалентные функции GETDATE()->UTC_TIMESTAMP(3), переименование переменных и параметров (тут было немного магии).
И после переписывались места для которых не было эквивалентной функциональности. Например где используются CTE, аналитические функции, конструкции IF THEN ELSE END IF (в T-SQL отличаются), и т.п.
Но в простых случаях после конвертации оставалось только расставить точки с запятой в конце statement-ов. Поначалу было медленно но потом разогнались и в итоге в день на человека выходило до 20 процедур. Причем большую часть времени занимало написание тестовых скриптов. В MariaDB / MySQL есть такая же проблема как в T-SQL пока вы не вызовете хранимую процедуру вы можете даже не узнать что у вас нет каких то таблиц или полей, поэтому без тестовых скриптов нельзя. Особенно пока не хватает функциональности для запуска интеграционных тестов на уровне бизнес слоя.
Что касается конвертиации DAC была предпринята попытка сделать код универсальным, в конце концов ведь нам нужно передать в хранимые процедуры одни и те же параметры и прочитать из резалт сета одни и те же поля. Типы на уровне БД отличаются но не отличаются на уровне приложения, таким образом фактически нужно только применять разные правила для data mapping и по другому обработать ошибки и исключения из БД.
Были разные причины, в том числе и нетехнического характера. Из технических я бы упомянул еще раз ричину которую я указал в статье: ситаксис T-SQL и MariaDb меньше отличается чем синтаксис T-SQL и PL/PgSQL. Хотя и на PostgreSQL наверное можно было мигрировать просто проблемы были бы другие, не те что с MariaDb.
Да, использовались. В MariaDb / MySQL тоже есть поддержка курсоров: mariadb.com/kb/en/mariadb/cursor-overview/ правда только non-scrollable но нам такие и требовались. Хотя разумеется часто код написанный с курсорами можно переписать без них.
DECLARE vHost VARCHAR(512);
DROP TEMPORARY TABLE IF EXISTS __HostsToProcess__;
CREATE TEMPORARY TABLE __HostsToProcess__ ENGINE=MEMORY
AS SELECT Host FROM User;
WHILE EXISTS (SELECT 1 FROM __HostsToProcess__ LIMIT 1) DO
SET vHost = (
SELECT Host FROM __HostsToProcess__ LIMIT 1);
SELECT CONCAT("Process host: ", vHost);
DELETE FROM __HostsToProcess__
WHERE Host = vHost;
END WHILE;
DROP TEMPORARY TABLE IF EXISTS __HostsToProcess__;
Я не конца понимаю что было в головах продакт менеджеров, но основная идея мне кажется на поверхности. SQL Server стоит денег и если мы можем предложить продукт тем для кого эти деньги существенные, но им не столь важны фичи SQL Server почему бы это не сделать.
Используя принцип Оккама не умножать сущности без необходимости )
Вывод времени события в таймзоне пользователя относится к презентационной логике и конвертация в локальное время пользователя по моему скромному времени должна быть только там а не в хранимых процедурах и не в каком либо t-sql.
То же самое относится к загрузкам данных, у разных источников данных могут быть разные соглашения о формате времени и таймзоне, но задачу конвертации в один общий формат и одну таймзону БД лучше решать именно там в каждом конкретном сервисе загрузки данных.
Кстати таймзона БД не обязательно должна быть UTC, иногда удобнее хранить данные в таймзоне локальной для основной команды разработки. Но главное чтобы к этой таймзоне не применялись правила DST. То есть если EST так уж EST никаких там ESD.
Но все равно на мой взгляд прекрасное решение в описанных условиях, что бы не говорили об этом другие коллеги )
Причем вторая функция была примеров использования .Net расширения для SQL Server.
И шардинг можно реализовать довольно просто на sql, благодаря родному механизму репликации.
Одна проблема — больно дорого. Энтерпрайз версия сервера это $NNk на сокет.
А в кластере из N узлов получается $NNNk, а то и $NNNNk чисто на лицензии...
Строго говоря индексы к реляционной модели данных никакого отношения не имеют.
Индексы это способ ускорить обработку данных.
Но это все не так важно. Важно что нужно с чего-то начинать. И в данном случае было проще начать с корпоративного рынка.
А как учил нас Джаэл Спольски, чтобы иметь успех в массовом сегменте нужно чтобы твой процессор умел запускать Word и Excel.
Но даже это сейчас не гарантирует удачи, как показал пример Surface RT на ARM-е. Оказывается пользователи хотят чтобы работали все все сотни тысяч и даже миллионы существующих приложений к которым они привыкли.
А чтобы hadoop кластеры заработали на Power8 нужно всего лишь портировать Linux и Java.
Если удаться распространить технологию на энтерпрайзные кластеры со временем будет портироваться больше софта и возможно и массовый сегмент подтянется.
Конечно я может быть не понимаю всех нюансов кодирования на уровне ядра, но все же… функция очень длинная, я бы разделили ее на три по одной для каждого из поддерживаемых значений ThreadInformationClass и вызывал их из NtUserSetInformationThread.
Кроме того я бы перенес вызов UserEnterExclusive() туда где он действительно необходим, во всяком случае после проверки аргументов, которые наверняка можно проверять без эксклюзивного режима.
ThreadHandle используется не во всех кейсах switch-а, я бы делал вызов ObReferenceObjectByHandle(ThreadHandle, ...) только по необходимости и только для тех ThreadInformationClass для которых он действительно нужен, и опять же после проверки аргументов.
Зачем захватывать ресурсы которые не нужны?
Сообщение ERR(«Shutdown initiated\n») на самом деле не всегда будет говорить правду. Потому что если аргументы не пройдут проверку UserInitiateShutdown() не будет вызван и соотвественно сообщение Shutdown initiated в логах будет говорить не правду.
Кейс когда нужно проверить указатель на возможность чтения или записи и вернуть NTSTATUS наверное не единственный. Для этого можно иметь одну inline функцию или макрос которая(ый) будет использоваться везде.
И эта функция не единственная где есть похожие проблемы (
Можете мне сказать что предлагаемые изменения сделают код более длинным, добавят в стек исполнения еще один вызов функции что негативно повлияет на производительность. Это все правда. Но они точно улучшат читабельность и понятность кода что приведет к повышению безопасности.
Как то так… Может быть я и не прав.
Но так или иначе если вы видите сейчас более правильное / красивое / эффективное решение скорее всего это можно исправить.
T-SQL хранящийся в таблицах в БД, если я правильно понял суть проблемы, не отличается от хранимых процедур, его тоже можно переписать изменив подход, разве нет?
Если вернутся к dynamic SQL — то его главный недостаток в SQL Server в том что он забивает квери кэш который становится большим и теряет эффективность. (В MariaDb такой проблемы нет по той причине, что query cache там лучше даже не включать :)
Что касается конвертации процедур то подход был такой:
Был powershell скрипт для предварительной подготовки текста, с теми заменами которые можно сделать с помощью regexp, например типы данных XML->LONGTEXT,UNIQUEIDENTIFIER->BINARY(16), и т.д., эквивалентные функции GETDATE()->UTC_TIMESTAMP(3), переименование переменных и параметров (тут было немного магии).
И после переписывались места для которых не было эквивалентной функциональности. Например где используются CTE, аналитические функции, конструкции IF THEN ELSE END IF (в T-SQL отличаются), и т.п.
Но в простых случаях после конвертации оставалось только расставить точки с запятой в конце statement-ов. Поначалу было медленно но потом разогнались и в итоге в день на человека выходило до 20 процедур. Причем большую часть времени занимало написание тестовых скриптов. В MariaDB / MySQL есть такая же проблема как в T-SQL пока вы не вызовете хранимую процедуру вы можете даже не узнать что у вас нет каких то таблиц или полей, поэтому без тестовых скриптов нельзя. Особенно пока не хватает функциональности для запуска интеграционных тестов на уровне бизнес слоя.
Что касается конвертиации DAC была предпринята попытка сделать код универсальным, в конце концов ведь нам нужно передать в хранимые процедуры одни и те же параметры и прочитать из резалт сета одни и те же поля. Типы на уровне БД отличаются но не отличаются на уровне приложения, таким образом фактически нужно только применять разные правила для data mapping и по другому обработать ошибки и исключения из БД.