Ответы пользователя по тегу Базы данных
  • Как проще хранить информацию?

    Melkij
    @Melkij
    PostgreSQL DBA
    В одной партицированной таблице.
    Ответ написан
    2 комментария
  • Как оптимизировать базу данных?

    Melkij
    @Melkij
    PostgreSQL DBA
    1. Поле типа varchar всегда занимает минимум 1 или 2 байта на диске, в зависимости от максимальной длины этого поля. В индексах и при операциях в памяти разворачивается до своего максимального размера (подобно char). Больше данных -> меньше данных влезает в кеш -> больше нагрузка на диски -> медленнее работа.
    На таком смешном размере таблицы не имеет никакой роли. Если это уже потребовалось оптимизировать - огромные грабли в другом месте.
    2. Да, на диске varchar хранит только то, что положили в поле. Плюс 1 или 2 байта оверхеда на хранению длины записанной строки.
    Ответ написан
    Комментировать
  • Rак правильно организовать списание баланса?

    Melkij
    @Melkij
    PostgreSQL DBA
    InnoDB все запросы выполняет только в транзакции. Если открытой транзакции не было, то этот запрос неявно оборачивается в транзакцию.
    Вот только сами по себе транзакции не помогут, надо ещё правильно ими пользоваться. Тут я бы хотел дополнительно обратить внимание Андрей:
    Попробуйте в двух терминалах написать:
    сначала begin; в обоих
    потом select из таблички. Значения одинаковые, правда?
    потом update этой же таблички, сделайте set fieldname = разные значения в терминалах. Второй терминал запрос принял, но не вернул управление, верно?
    потом commit; в первом терминале. update из второго терминала сразу же ответил OK.
    Теперь сделайте commit во втором терминале и посмотрите, что произошло с данными. Это то, на что вы рассчитывали? Или всё-таки не совсем?

    N пользователей запрашивают услугу одновременно, корректно ли произойдет списание средств?

    Нет, некорректно, если только вы не в одной транзакции и не читаете баланс специально с select .. for update.
    Потому что для выполнения действия $this->balance -= $sum; у вас уже должен быть известен баланс, но это ещё не операция записи.
    В итоге у вас было 1000 рублей.
    Пришёл один клиент, прочитал баланс, хочет списать 200 рублей. Обновил циферку в PHP, никто ему не мешает.
    Пришёл второй клиент, прочитал баланс, хочет списать 100 рублей. Обновил циферку в PHP, никто ему тоже не мешает.
    И на шаге save оба отправили запросы на update: один клиент считает, что на балансе осталось 800 рублей, второй - что 900.
    Сколько запишется на баланс? 800 или 900, как повезёт. Правильно ли это? Сколько должно было быть? 700 ведь.
    Потому что клиенты не мешали друг другу обновлять циферку в PHP.

    Как же заставить клиентов не делать глупости?
    В простом случае:
    update tablename set balance = balance - :amount where balance >= :amount and user_id=:uid
    И на приложении проверять affected_rows. Если строка изменена - у пользователя достаточно денег, платёж прошёл. Если изменённых строк нет - вероятно, у пользователя нет столько денег. СУБД разберётся с очерёдностью исполнения и в результате на балансе будет правильная сумма, сколько бы параллельных запросов ни пришло. И, что не менее важно - приложение ответит на все запросы корректно, кому денег хватило, а кому - уже нет.

    В более сложных случаях - можно самому попросить СУБД взять блокировку на строку, о чём чуть ранее я уже заикался:
    begin;
    select balance from tablename where user_id=:uid for update; -- все параллельные транзакции будут выстраиваться в очередь здесь
    /* произвольные запросы (в mysql кроме вызова хранимок, DDL - они делают неявный коммит). Среди этих запросов - обновляете баланс */
    commit; -- только здесь эта транзакция освобождает блокировку select .. for update и с этой строкой начинает работать следующий запрос

    Как вообще работать с деньгами и делать это правильно - Кирилл даёт правильное направление. Изучите, как это делает бухгалтерия, за многие десятилетия работы они придумали, как обходить много странных граблей.
    Ответ написан
    2 комментария
  • Почему не добавляется внешний ключ?

    Melkij
    @Melkij
    PostgreSQL DBA
    Определения полей должны совпадать.
    int и unsigned int - разные типы полей.

    Ну и, конечно, таковая строка должна существовать.
    Ответ написан
    2 комментария
  • Как создать MySQL запрос для выборки из двух таблиц?

    Melkij
    @Melkij
    PostgreSQL DBA
    select date1, temp1, temp2 from table2 join (
    select date1, temp1 from table1 where date1 >= :period_from and date1 <= :period_till order by temp1 desc limit 1 -- по старому обыкновению, мог перепутать asc/desc
    ) mintable1 ON date1 = date2
    Ответ написан
  • Нестрогая типизация Incorrect integer value: '' for column, как исправить?

    Melkij
    @Melkij
    PostgreSQL DBA
    Правильно: исправьте свой бекенд. Передавайте числа как числа.
    Похуже: как указал Дмитрий Ким или более явно IF(:tekstura != '', :tekstura, 0)
    Худший и что, собственно, отличает этот хост от другого, где этот запрос проходит нормально: изменить sql_mode https://dev.mysql.com/doc/refman/5.6/en/sql-mode.html
    Ответ написан
    1 комментарий
  • Как разбить таблицу MySql и стоит ли?

    Melkij
    @Melkij
    PostgreSQL DBA
    Даже для такой удивительной штуки, как mysql, лям записей - это фигня. Сто лямов - посерьёзнее, но тоже фигня.
    Почитать explain'ы и профилирование, что-нибудь можно партицировать штатным механизмом партицирования mysql.

    Более логичные решения - взять postgresql.
    Ответ написан
    4 комментария
  • Как ускорить запрос в postgresql?

    Melkij
    @Melkij
    PostgreSQL DBA
    По порядку:
    Повторно запрос выполняется много быстрее.

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

    В конфиге postgresql менял настройки только авторизации.

    По дефолту там что-то несмешное вместо shared_buffers. 32 что ли мегабайта? И это на ключевую характеристику базы.
    Увеличивать хотя бы до 20% от общего объёма памяти на машине.

    В третьих, актуальный Postgresql довольно плохо умеет развесистый IN. И тому есть не совсем очевидное решение - переписать в join:
    select count(*) from test JOIN (VALUES (1),...,(10000)) AS v(val) USING (val);

    Такой вот hash join работает быстрее IN. На 10000 элементах получали 10мс против 380мс у IN.
    Ответ написан
    Комментировать
  • Как в триггерах ссылаться на таблицы и поля этих таблиц?

    Melkij
    @Melkij
    PostgreSQL DBA
    Поскольку не указано, о какой СУБД речь, скажу о postgresql и mysql
    www.postgresql.org/docs/9.4/static/plpgsql-trigger.html
    https://dev.mysql.com/doc/refman/5.6/en/trigger-sy...
    Мануалы и той и другой СУБД вполне показывают и ссылки на OLD/NEW и какие-то операции над данными.
    Ответ написан
    Комментировать
  • Как спроектировать масштабируемую систему для подсчета показов баннеров?

    Melkij
    @Melkij
    PostgreSQL DBA
    adriver?
    Ответ написан
    Комментировать
  • Как реализовать реконект к БД каждые N секунд?

    Melkij
    @Melkij
    PostgreSQL DBA
    В чём проблема? Зациклите код вместо exit'а по условию успешности установленного коннекта
    Псевдокод:
    is_connect_success = false
    do
    try
    //connect
    is_connect_success = true
    except
    print error
    sleep 5 seconds
    while (is_connect_success)
    Ответ написан
  • Как автоматизировать перенос данных из одной БД в другую?

    Melkij
    @Melkij
    PostgreSQL DBA
    Возьмите любой протокол организации VPN или даже банально ssh-тунель - и будет двусторонняя связь.
    Если второй СУБД данные из первой нужны только на чтение - то реплику настроить.
    Ответ написан
    Комментировать
  • Как ускорить выполнение SQL запроса?

    Melkij
    @Melkij
    PostgreSQL DBA
    count довольно дорогая операция.

    Сделайте отдельную таблицу для аггрегированных данных: status tinyint, count int. Поддерживать актуальность данных пачкой триггеров: на insert увеличиваете счётчик нужного status, на update уменьшаете OLD.status и увеличиваете NEW.status, на delete уменьшаете status.
    Ответ написан
    2 комментария
  • MySQL, запрос, одинаковые значения?

    Melkij
    @Melkij
    PostgreSQL DBA
    select id, coords from orders join (
    select coords from orders group by coords having count(0)>1
    ) nonuniqcoords using(coords)
    Ответ написан
    Комментировать
  • Как ускорить выполнения SQL запросов?

    Melkij
    @Melkij
    PostgreSQL DBA
    Использовать локальный кэш тоже не очень хороший вариант, т.к. в БД могут писать их других мест, а данные нужны актуальные.

    Использовать локальный кеш. Обновляются данные явно не каждые 1мс, за которые вы боретесь.
    Обновление - вплоть до из триггера пинать UDF, которая сообщит вашему приложению, что данные в БД обновились.
    Ответ написан
    1 комментарий
  • Какие книги по MYSQL вы использовали для обучения?

    Melkij
    @Melkij
    PostgreSQL DBA
    "High Performance MySQL", Baron Schwartz, Peter Zaitsev, Vadim Tkachenko
    shop.oreilly.com/product/0636920022343.do
    Не просто достойна. а обязательна к прочтению всем, кто работает с MySQL.
    Ответ написан
    Комментировать
  • Как сформировать запрос к MySQL?

    Melkij
    @Melkij
    PostgreSQL DBA
    Простейший update без условия, вопрос-то в чём?
    Ответ написан
    3 комментария
  • Как настроить репликацию PostgreSQL с серого IP-адреса?

    Melkij
    @Melkij
    PostgreSQL DBA
    Туннель, может лучше будет сделать?
    Поверх SSH или какой-нибудь VPN.
    Ответ написан
    2 комментария
  • Как массово разбросать информацию из одного столбца таблицы в несколько других?

    Melkij
    @Melkij
    PostgreSQL DBA
    start transaction
    select id, info from users for update; в PHP
    Каким угодно методом на стороне php разбираете этот свой формат на необходимые части
    update users set ... where id=?
    commit;
    Можно кусками по сотне записей, если на время обновления всё залочить нельзя.
    Ответ написан
    Комментировать
  • Какие книги\публикации\курсы почитать\прослушать по Архитектуре и разработке СУБД ?

    Melkij
    @Melkij
    PostgreSQL DBA
    Некоторое время назад у нас на работе семинар проходил. Я так глубоко не залезал, но помимо "Architecture of a Database System" приглашённым DBA упоминались ещё несколько книг как заслуживающие внимания:
    Gerhard Weikum, Gottfried Vossen - "Transactional Information Systems: Theory, Algorithms, and the Practice of Concurrency Control and Recovery"
    Tom Kyte - "Effective Oracle by design"
    И ещё несколько, которые уже читал - но они про использование СУБД, а не внутреннюю кухню.
    Ответ написан
    Комментировать