Ответы пользователя по тегу MySQL
  • Стоит ли подготовить все запросы в init?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    Прежде чем использовать подготовленные запросы прочитайте это:
    - go-database-sql.org/prepared.html
    - go-database-sql.org/surprises.html

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

    Если вам важно увеличить пропускную способность простых INSERT то посмотрите в сторону HandlerSocket, уверен под Golang оно уже должно было появиться, если нету - сможете реализовать самостоятельно, протокол не особо сложный.
    Ответ написан
    Комментировать
  • Как кешировать однотипные MYSQL UPDATE?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    Накапливайте в памяти. Вы не указали язык программирования на котором такая задача.

    PHP - можно сделать in-memory таблицу в MySQL и делать туда всё теже UPDATE `news` SET `views`=`views`+1, раз в N минут обновлять основную таблицу данными из in-memory (добавлением, а не заменой значения, иначе при рестарте сервера при очередном обновлении потеряются часть показателей)
    Golang - хранить количество просмотров в памяти с RWMutex защитой, раз в N минут сохранять все накопленные изменения в MySQL базу

    Так же можно использовать Memcache, shared memory, любые другие базы данных, исходя из:
    • языка программирования
    • доступного инструментария


    Так же можно вынести views поле в отдельную таблицу или даже на другой MySQL сервер:
    • либо отдельно views
    • либо сделать копию таблицы news

    При этом можно добавить очередь (RedisMQ или что-либо другое) для асинхронного увеличения news.views, принцип следующий:
    • пользователь запросил страницу - сделалось SELECT
    • сделали задание в очередь на обновление статистики
    • пользователь получил страницу
    • через какое-то время задание по обновлению количества просмотров выполнилось и пользователь ничего не ждал
    Ответ написан
  • Какой фомат БД использовать для большого количества записей и чтения и таблицы?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    Если MySQL принципиален - попробуйте HandlerSocket, улучшит запись и чтение соответственно, но потребует изучения нового API.

    Небольшое описание со ссылками есть в другом моём ответе по смежному вопросу: Вопрос по подключению системы кэширования?
    Ответ написан
    Комментировать
  • Как убрать дубликаты в mysql запросе?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    SELECT distinct to_id FROM messages WHERE from_id = 5
    SELECT distinct from_id FROM messages WHERE to_id = 5

    Почитайте более подробно тут: www.mysql.ru/docs/man/DISTINCT_optimisation.html

    Одним запросом можно сделать через UNION (объединение нескольких запросов)
    SELECT to_id as user_id FROM messages WHERE from_id = 5
    UNION
    SELECT from_id as user_id FROM messages WHERE to_id = 5

    Подробнее про UNION и DISTINCT с его участием тут: www.mysql.ru/docs/man/UNION.html

    Если не используется ключевое слово ALL для UNION, все возвращенные строки будут уникальными, так как по умолчанию подразумевается DISTINCT для всего результирующего набора данных. Если указать ключевое слово ALL, то результат будет содержать все найденные строки из всех примененных команд SELECT.

    И ещё один способ с обычным DISTINCT одним запросом:
    SELECT
        DISTINCT IF(to_id = 5, from_id, to_id) as user_id
    FROM messages
    WHERE from_id = 5
        OR to_id = 5


    Для тех кому лень читать ссылки: DISTINCT во многих случаях разворачивается в GROUP BY и использует временную таблицу. Вывод - если важно отфильтровать дубли только в какой-то конкретной колонке то:
    1. можно указать distinct у конкретного поля (distinct from_id), не для этого случаях, вспомнить подходящий с ходу не удалось
    2. можно указать GROUP BY и перечислить нужные поля не указывая DISTINCT


    Подсчёт дополнительной колонки unread и вывод даты последнего сообщения:
    SELECT
        IF(to_id = 5, from_id, to_id) as user_id,
        SUM(unread) as count_unread,
        MAX(create_date) as last_create_date
    FROM messages
    WHERE from_id = 5
        OR to_id = 5
    GROUP BY user_id


    Добавляем LEFT JOIN (хотя их использовать и не стоит)
    SELECT
        IF(m.to_id = 5, m.from_id, m.to_id) as user_id,
        SUM(m.unread) as count_unread,
        MAX(m.create_date) as last_create_date,
        u.name,
        u.login
    FROM messages as m
        LEFT JOIN users as u ON (u.user_id = m.from_id OR u.user_id = m.to_id)
    WHERE m.from_id = 5
        OR m.to_id = 5
    GROUP BY user_id
    Ответ написан
  • Golang mysql: Invalid Connection?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    Прослеживаем цепочку через документацию
    1. https://github.com/go-sql-driver/mysql используется совместно со стандартным https://golang.org/pkg/database/sql/
    2. находим в https://golang.org/pkg/database/sql/ функцию
    func (db *DB) Query(query string, args ...interface{}) (*Rows, error)

    3. видим что результат *Rows, находим эту структуру и изучая находим функцию
    func (rs *Rows) Close() error
    4. точно такую же функцию видим у Stmt
    func (s *Stmt) Close() error
    5. делаем вывод что надо закрывать соединения, в определённых случаях, принудительно

    Подобный вопрос был на toster.ru уже разва два.
    Вот тут можете прочитать дискуссию по поводу особенностей работы с MySQL в Golang: https://toster.ru/answer?answer_id=685014#comments...

    Полезные ссылки для тех кто хочет разобраться в вопросе:
    4gophers.ru/article/go-i-sql-bazy-dannyh
    go-database-sql.org/surprises.html
    Ответ написан
    1 комментарий
  • Как избавиться от надоедливой строки в MySQL?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    Скопируйте данные в новую базу, хоть построчно хоть через mysqldump, весь вопрос в том что вообще ещё работает.
    Ответ написан
    Комментировать
  • Что скажете о моей реализации логирования?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    Посмотрите в сторону уже готовых систем логирования (Graphite, influxdb, прочее) и мониторинга (mrtg, rrd).

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

    По поводу бенчмарков. Вы утверждаете что "вставка в редис"+"вставка в mysql" работает быстрее чем "вставка в mysql". Это по меньшей мере выглядит заблуждением, потому что тот же редис на том же сервере (на сколько я понял) и производительности прибавить не может. Изменился разве что немного подход к записи в MySQL.

    Варианты которые у вас были при написании своего логера:
    1. писать в MySQL по запросу каждый раз когда срабатывает некое событие и появляется запись в логе
    2. накапливать пачку логов в оперативной памяти - пушить в MySQL точно так же как после редиса (долой редис), за одно научитесь ограничивать потребление памяти (вы ведь не можете бесконечно склодировать данные)
    3. накапливать пачку логов в файл (банальный бинарный файл), раз в N минут менять лог-файл
    4. вариант тот же что и третий, только старые логи переносить в базу в фоне.

    Тут надо так же обратить внимание на то для чего логи пишутся:
    1. что бы точно знать кто где и что делал (доктилоскопия пользователей)
    2. что бы делать реал-тайм подстройку других алгоритмов в зависимости от поведения пользователей, системы и всего такого
    3. что бы просто быть в курсе что приложение упало (кстати в этом случае ваш код отправит емейл?:))

    У меня есть задача по сохранении метрики всякой. Условия:
    1. MySQL - для показа потом агрегированных графиков и просто списков что сделалось за определённый промежуток времени.
    2. Shared-хостинг где можно запускать бинарники, но нельзя делать fork'и и по сути ставить ничего кроме Golang приложения и PHP скриптов.
    3. Golang приложение которое щёлкает задачки как семечки и метрик просто туча - считай только их и писать.

    Без накопления и группировки MySQL только и занимается что вставкой в таблицу с метрикой. В планах хранить в бинарных блобах. Ставить тот же Графит на Shared-хостинг для такой простой задачки считаю избыточно:)
    Ответ написан
  • Как правильнее записывать данные в 2 связанных таблицах?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    Если я вас правильно понял то вы:
    1. на входе имеете массив тегов $tags = array("tag1", "tag2", "tag3")
    2. хотите сохранить новые в базу
    3. хотите получить id всех тегов и присвоить их к некоторому посту

    Попробуйте сделать так:
    1. INSERT IGNORE INTO `tags` (title) для всех тегов, те что есть проигнорируются
    2. SELECT id FROM `tags` WHERE `title` IN (...) для всех тегов что вам нужно
    3. INSERT IGNORE INTO `post_tags` для всех id полученных из второго запроса

    По крайней мере это уменьшит количество кода и упростит понимание.
    + добавьте слой кеширования для хранения тегов которые уже добавлены в базу (их ведь особо много явно не будет)
    Ответ написан
  • Где лучше хранить большие списки int'ов?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    Это вполне типичный blob:)
    Ответ написан
    1 комментарий
  • "Разработка cms" как тема диплома?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    Дипломная работа предполагает некоторое исследование, некий поставленный вопрос и процесс получения на него ответа. Научная работа, одним словом. Если хотите сделать разработку CMS дипломным проектом то и подходите к ней как к диплому, со всеми вытекающими от сюда особенностями.

    Придумайте методику, подкрепите её знаниями и исследованиями, проведите ряд экспериментов, а там глядишь и диплом будет с чего писать.
    Ответ написан
    5 комментариев
  • Почему mysql возвращает ошибку?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    Школьник, ты по одной задаче открыл тонну связанных вопросов... учись группировать данные.
    Ответ написан
  • Есть ли для Go библиотека работы с mysql?

    @mantyr
    Пишу много Golang кода с удовольствием:)
    1. db, err := sql.Open() требуется вызвать один раз, нет нужды на каждый запрос писать этот кусок кода
    2. panic(err.Error()) - падать приложение в паник плохая практика, если вам нужен некий комплект данных, то сделайте функцию или метод который возвращает данные и ошибку (если есть)
    3. log.Fatal(err) - так много логов вам не нужно. Суть в том что если вы получили ошибку, то вам нужно завершать текущий блок кода, а не продолжать его дальше. Ведь если вы не смогли получить данные из базы, то бегать по данным вам так же не нужно.

    Пример того как это можно оформить play.golang.org/p/polc_jwrF7 правда я не использовал реальный модуль для MySQL и часть кода не дописано, так как это вы уже как-нибудь сами.
    Ответ написан
    1 комментарий