Задать вопрос
  • Как правильно задать запрос UPDATE где название столбца переменная?

    @Vitsliputsli
    Какую нормальную форму нарушает текущая реализация?
    То, что вы предлагаете не нормализация, а переход к EAV, которая применяется при большой вариативности атрибутов, но небольшом их кол-ве для каждой сущности.
    Когда необходим поиск по разным столбцам таблицы берут и создают запросы динамически с помощью какого-либо билдера, т.е. "задают имя столбца через переменную". Никто ради этого не переводит таблицу в формат EAV или похожий.
    Пока неизвестны все варианты работы с данными однозначно зявить что нужна только какая-то конкретная схема нельзя. Так для EAV адресация будет работать медленней из-за составного ключа, объем хранимых данных также может вырасти, а не уменьшиться, а если окажется, что автору нужно выводить аттрибуты как таблицу, то привет pivot (т.е. столько join, сколько атрибутов будем выводить).
    Т.е. если и нужна EAV, то точно не по указанным причинам.
  • Как правильно задать запрос UPDATE где название столбца переменная?

    @Vitsliputsli
    Ипатьев, еще раз, я привел вариант как это сделать несколькими простыми строчками на php, и вы его видели. И все они касаются только маппинга из входных данных в текщее хранилище, то что вы не делаете маппинг, а используете входные данные как есть, уменьшает код, но не факт, что в будущем это не выйдет боком. Ну нельзя выбирать схему хранения, только потому, что захотелось сэкономить на маппинге.
  • Как правильно задать запрос UPDATE где название столбца переменная?

    @Vitsliputsli
    Ипатьев,
    нормализация - это серебряная пуля и панацея. Один из ключевых принципов архитектуры.
    И не надо ставить денормализацию на одну доску с ней. Это не принцип проектирования баз данных, а компромисс, который никогда не закладывается исходно, а добавляется сильно позже, когда (если) возникают проблемы с производительностью.

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

    Чем схема плоха, я наглядно показал в своем ответе - при нормальной схеме - когда номер счетчика уходит в условие, где он и должен быть - сразу пропадает ВЕСЬ этот говнокод, и делается простой запрос апдейт.

    А где говнокод? Динамический SQL? Да он присутствует практически в любом проекте, и то, что у автора он собирается не так элегантно как в популярном фреймворке, ни разу не говнокод. Как сделать боле читабельным код на php и убрать гонку я показал, но схема БД здесь не при чем. Да и называть любой не свой код говнокодом, это так себе...
    И вы ничего не показали, ваш update ничем не лучше update с динамическим SQL. Пока мы больше не узнаем о том, как еще будут работать с этими данными (или как они соотносятся) бессмысленно говорить о "плохих" схемах. Про производительность и место для хранения вообще молчу, я так понял на это забиваем, но все же какую нормальную форму нарушает текущая схема?
  • Как правильно задать запрос UPDATE где название столбца переменная?

    @Vitsliputsli
    Ипатьев, ага, проглядел этот момент. Очевидно, что в случае неопределенного кол-ва параметров не получится создать неопределенное кол-во столбцов. Согласен, надо было на это обратить внимание.
    В общем случае, нормализация не панацея и не серебрянная пуля, а денормализация наш повседневный инструмент. Специализация может оказаться более важной, чем универсализация. Да и с данными там непонятно, там вполне может оказаться, что это все же один и тот же объект с вполне определенными свойствами, т.к. автор не сознается об истинных данных, и явно заменяет их примерами из головы, что при этом потерялось неизвестно.
    И, повторюсь, проектировать бд нужно исходя из того, как ей будут пользоваться, а не только исходя из данных.
    И, кстати, чем схема то плохая? Если параметров 3.
  • Как правильно задать запрос UPDATE где название столбца переменная?

    @Vitsliputsli
    Ипатьев, если плодить то будет печально, действительно не указал на это. Но, насколько я понял, они у автора не плодятся, а есть объект с 3 свойствами. Если есть подозрение, что будут плодиться, то очевидно, что существующий вариант не лучший.
    В любом случае, выбрать наилучший вариант невозможно, не зная все о данных и вариантов обращений к ним.
  • Как правильно задать запрос UPDATE где название столбца переменная?

    @Vitsliputsli
    Михаил Смирнов, текущая схема вполне себе неплохая, но с точки зрения реляционной модели нужно сделать составной ключ, т.е. таблица будет выглядеть примерно так:
    id_part1 id_part2 count
    21 1 3
    21 2 4
    здесь первичный ключ составной id_part1 + id_part2.
    В принципе, не так принципиально какой вариант выбрать, если только у вас нет повышенных требований к производительности. А если есть, то нужно исходить из запросов которые вы будете делать, а не только от хранимых данных.
  • Как правильно задать запрос UPDATE где название столбца переменная?

    @Vitsliputsli
    Ипатьев, он идентичен только функционально. К функциональности вопросов нет, но у кода есть не только функциональность, есть такая штука как читаемость, и это не вкусовщина.
    Представьте что вы не читали задание и не знаете что нужно сделать и посмотрите на запрос:
    UPDATE `list` 
            SET count1 = CASE WHEN id = ? AND ? = 1 THEN count1 - ? ELSE count1 END,
                count2 = CASE WHEN id = ? AND ? = 2 THEN count2 - ? ELSE count2 END,
                count3 = CASE WHEN id = ? AND ? = 3 THEN count3 - ? ELSE count3 END
            WHERE id = ?

    сколько времени уйдет, чтобы понять что он делает? Подскажу - бесконечность. Не зная, что конкретно подставляем вместо вопросиков, что он делает неизвестно. Давайте улучшим, добавим именованые параметры:
    UPDATE `list` 
            SET count1 = CASE WHEN id = :id_part1 AND :id_part2 = 1 THEN count1 - :count ELSE count1 END,
                count2 = CASE WHEN id = :id_part1 AND :id_part2 = 2 THEN count2 - :count ELSE count2 END,
                count3 = CASE WHEN id = :id_part1 AND :id_part2 = 3 THEN count3 - :count ELSE count3 END
            WHERE id = :id_part1

    Уже лучше, теперь смотря только на запрос можно понять, что он делает, не спервого взгляда, но можно.
    Но, лучше ли читаемость, чем если бы мы это сделали на php? Сравним:
    const COLUMNS = [
        1 => 'column1',
        2 => 'column2',
        3 => 'column3',
    ];
    $column = COLUMNS[$id[1]];

    UPDATE `list`  SET $column = $column - :count WHERE `id` = :id_part1

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

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

    @Vitsliputsli
    Анастасия Foxman, вы и на работе на комментарии при ревью так реагируете? Не воспринимайте это лично, это претензия к коду, а не к вам, только так можно улучшать код и свои навыки. Свой вариант я написал в комментариях, можете также сделать ревью для него.
    Комментарии это хорошо, но лучше, когда они не нужны, и все понятно из кода.
  • Как правильно задать запрос UPDATE где название столбца переменная?

    @Vitsliputsli
    А теперь представьте, что вы смотрите на этот код через полгода-год, или вообще другой человек смотрит, сколько времени уйдет на то, чтобы понять что тут творится? И что этот человек подумает, когда поймет, что это на самом деле просто UPDATE `list` SET $column = ? WHERE `id` = ?
  • Как правильно задать запрос UPDATE где название столбца переменная?

    @Vitsliputsli
    Для защиты от SQL-инъекций достаточно:
    $column = 'count' . (int)$columnNumber;
    Хотя для такой подстановки, если столбцов вменяемое кол-во, я бы лучше сделал так:
    const COLUMNS = [
        1 => 'column1',
        2 => 'column2',
        3 => 'column3',
    ];
    if (!isset(COLUMNS[$id])) {
        throw new \InvalidColumnException();
    }
    $column = COLUMNS[$id];

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

    Но, если делать рефакторинг, то я бы в первую очередь обратил бы внимание, что за странные id с тире внутри и вообще зачем динамические столбцы.
  • Лег сервер, нагрузка CPU 100%. Что делать?

    @Vitsliputsli
    Дмитрий Сериков,

    Я не админ, так понимаю лежит сервер БД

    Где вы это увидели? По процу на нем нагрузка 0. Отсортируйете по процу ваш htop, чтобы увидеть, что реально грузит проц.
  • Можно ли всем строковым полям задавать тип TEXT и повлияет ли это сильно на производительность?

    @Vitsliputsli
    Сергей Соловьев, перепроверил, должен исправиться, в PostgreSQL тип char реализован по-мудацки, поэтому в этой СУБД его действительно лучше не использовать. Так что вы правильно написали, а мой пример некорректен для PostgreSQL.
  • Можно ли всем строковым полям задавать тип TEXT и повлияет ли это сильно на производительность?

    @Vitsliputsli
    Melkij, а какая разница для вопроса, какие у него лавры? Если он нормально не объясняет в ответе.
    Но должен исправиться, в PostgreSQL тип char реализован по-мудацки, поэтому в этой СУБД его действительно лучше не использовать, но при нормальной реализации как в других СУБД это не так.
  • Можно ли всем строковым полям задавать тип TEXT и повлияет ли это сильно на производительность?

    @Vitsliputsli
    Приведу полную цитату:
    Type character(N) is a hangover from the days of punched cards.
    Don't use it. It has weird semantics concerning trailing spaces,
    which are almost never the behavior you actually want, and cause
    interoperability issues with type text. (Text is Postgres' native
    string type, meaning that unlabeled string constants will tend to
    get resolved to that.)

    т.е. единственная претензия к типу, что Том не знает как он работает, и для него неожиданно поведение этого типа. С другой стороны отвечая на вопрос того, кто создает такие поля:
    contract_address character(42) NOT NULL,
    buyer_address character(42) NOT NULL,
    seller_address character(42) NOT NULL,

    такому действительно можно рекомендовать лучше вообще не использовать тип char.
    char отличное решение там, где он действительно нужен, где строго определено кол-во символов. но если у вас не высоконагруженное решение, и лишний байт на каждое поле не проблема, то можно всегда использовать varchar.
  • Можно ли всем строковым полям задавать тип TEXT и повлияет ли это сильно на производительность?

    @Vitsliputsli
    MishaXXL,

    По поводу памяти это экономия на спичках использовать VARCHAR или за этим следят?

    Используйте те типы, которые подходят для ваших данных, не с точки зрения производительности сомнительно высчитаной, а с точки зрения стандартов SQL. Это нужно для правильной валидации данных и контроля данных. Объявляя параметр как text, вы не сильно ограничиваете его длину, а значит если понадобится хранить, передавать этот параметр в другую систему вы уже не сможете использовать тип varchar(255), а для другой системы это может быть критично. Чем более вы вносите ограничений в код и данные, тем легче будет ими управлять в будущем.

    Сергей Соловьев,
    varchar и text - по факту одно и то же, а char(n) как следует из документации самый медленный

    несовсем так, как написал выше, всегда выбирайте тот тип, который подходит под ваши данные. char(n) не самый медленный, а может быть даже менее затратный чем varchar, если вы в нем храните подходящие данные. Т.е. если вы храните например 2-х символьный код страны, char(2) - отличное решение, а вот varchar(2) будет затратнее, т.к. будет хранить ненужную здесь длину строки для каждой ячейки. Но, если вы возьмете тип char(255), и будете в нем хранить строки длиной 10 символов, то затраты будут в разы больше, чем для varchar(255). Поэтому используйте те типы, которые подходят для ваших данных.
  • Как определить тяжелые запросы?

    @Vitsliputsli
    Akina, автор сам сообразит какая цифра должна стоять, только он знает наверняка, для когото и в 10 раз меньше будет непозволительно долго.
  • Какой из вариантов схемы базы данных лучше?

    @Vitsliputsli
    разделить таблицу грузов так, что в одной таблице будут храниться атрибуты груза (габариты и вес), а в другой – экземпляры грузов

    Т.е. в одной будет хранится описание товара, а в другой конкретные экземпляры, где-то представленные, тогда да, это правильно, это нормализация.
  • Как удалить запись в таблице MySQL по трём параметрам?

    @Vitsliputsli
    My1Name,

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

    Это искусственная проблема, т.к. проблемы по факту нет, но вы чтото хотите решить. Оптимизация это всегда жертва чемто ради чегото, поэтому нужно знать, что мы хотим улучшить, и чем готовы пожертвовать.
    В общем случае, обращение по первичному ключу всегда быстрее, чем по полям, хоть с индексом, хоть без. Первичный ключ есть всегда, то что вы не создали соответствующее поле, просто лишает вас возможности к нему обратиться, MySQL создаст его сам.
    А вопросы оптимизации чаще всего решаются проектированием БД, а не вставкой в запрос магической фразы "сделай все хорошо". Поэтому не будете менять структуру, не получите изменений.
  • Как удалить запись в таблице MySQL по трём параметрам?

    @Vitsliputsli
    My1Name,
    Проектируется большая БД (в теори, высоконагруженная частотой запросов) с множеством разных таблиц.

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

    Необходимо оптимизировать скорость доступа к одной записи.

    Тогда обращайтесь к этой записи по primary key, а не через индексы. Либо суррогатный ключ, как уже предлагали, либо составной ключ (и то, в этом случае надо посмотреть какие типы данных у этих полей).
  • Как удалить запись в таблице MySQL по трём параметрам?

    @Vitsliputsli
    My1Name, а в чем собственно проблема? чем мешает удаление по 3 полям? зачем хочется писать только 1 условие?