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

    Wolfnsex
    @Wolfnsex
    Если не хочешь быть первым - не вставай в очередь!
    Ещё есть вариант ссылки на другую таблицу, с набором заготовленных вариантов... Мы для себя выбрали ENUM, правда не в MySQL, а в PG, но сути дела это особо не меняет. Если внезапно нужно изменить таблицу (в PG нужно будет менять не таблицу, а ранее созданный тип данных) и добавить новый тип - это делается без особых проблем, т.к. у базы и проекта есть администраторы, контентщики и пр. обслуживающий персонал.

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

    В общем, на мой взгляд - вопрос больше личных предпочтений, я Вам озвучил наши :)
    Ответ написан
    Комментировать
  • Как запустить my sql php через cron?

    Wolfnsex
    @Wolfnsex Куратор тега PHP
    Если не хочешь быть первым - не вставай в очередь!
    Защитить этот файл - убрать у всех права на чтения и запись, кроме пользователя от которого он будет запускаться, это первый момент.

    Второй момент - не нужно так извращаться со временем, в MySQL есть стандартные функции для работы с ними, в т.ч. функция NOW() - возвращает текущие дату/время...

    *по поводу прав, это будут права 500, а по поводу работы с датами в MySQL - вот тут неплохо расписано.

    да, и не ставьте закрывающий тег ?> в конце PHP-файла, если там нет кода отличного от PHP, это может вызывать потенциальные проблемы с выводом всякого мусора в браузер и должно входить в привычку, даже если скрипт работает за пределами браузера.
    Ответ написан
    5 комментариев
  • Как логировать изменения с возможностью откатить?

    Wolfnsex
    @Wolfnsex
    Если не хочешь быть первым - не вставай в очередь!
    Изменения чего Вы хотите логировать? Базы или файлов? Если файлов - то GIT.

    Если базы, то миграции или, возможно, Git+миграции.

    Если ещё и данных в БД, то бекап БД (если база небольшая, то бекап в GIT).
    Ответ написан
  • Как организовать временное хранение картинок?

    Wolfnsex
    @Wolfnsex
    Если не хочешь быть первым - не вставай в очередь!
    Всё предельно просто.

    Первое, что Вам понадобиться - это смириться с мыслью, что для подобных задач предназначен планироващик, например, CRON. Не всем это нравится, но... по факту без него довольно сложно обойтись. CRON есть на любом нормальном хостинге, не говоря уже про какие-то более полноценные варианты (VPS, Dedic. и т.д.)

    У Вас есть картинки, которые привязаны (должны быть) к какому-то объявлению, которое создаётся ранее. С помощью CRON'а, вы находите объявления, которые более не ликвидны (недоопубликованы например) и по простой связи находите их картинки и удаляете всё сразу (и объявления и картинки).

    Другой вариант: у Вас объявление создаётся позже, чем картинки. То есть, картинки некоторое время, до полного формирования объявления существуют в некоем вакууме. В этом случае, Вы добавляете каждой картинке поле - "дата загрузки" и выбираете все картинки, дата загрузки которых была более суток назад и которые не привязаны ни к одному объявлению (т.е. поле объявление_id == NULL).

    Всё это делается по CRON'у, который запускает какой-то метод контроллера (судя по тому, что Вы используете Symfony). Обычно эту задачу решает утилита wget, которую запускает CRON. Что бы предотвратить "случайные" запуски со стороны пользователей - можно добавить проверку по GET-параметру, содержащему какой-нибудь хеш.
    Ответ написан
  • Почему MySQL не сразу фиксирует результат UPDATE?

    Wolfnsex
    @Wolfnsex Куратор тега PHP
    Если не хочешь быть первым - не вставай в очередь!
    Может есть какая-то функция закрытия запроса и процесс будет висеть пока MySQL не закончит?
    А какая разница, запаралеллится другой процесс PHP, пока тот будет висеть занимая пул, откроет новое соединение и сделает то же самое. Вы же не думаете, что PHP обрабатывает всех клиентов в 1 поток/скрипт? Пишите лог запросов, которые выполняются и будем разбираться, от чего именно такой порядок запросов, а а не какой-то другой.

    А вообще, в MySQL есть транзакции и блокировки, которые как раз защищают от таких случаев, когда кто-то что-то куда-то не успел, или не записал или... Попробуйте использовать их. Главное, не забудьте, что все операции записи/обновления должны проходить в одной транзакции, тогда подобных проблем не возникнет с вероятностью близкой к абсолюту.
    Ответ написан
  • Как оптимизировать ключи в MYSQL?

    Wolfnsex
    @Wolfnsex
    Если не хочешь быть первым - не вставай в очередь!
    В Вашем вопросе отсутствует солидная часть вводных данных. Какие ключи, где они "есть", сколько идёт выборка, почему именно INNER JOIN? и так далее.

    Ключи (индексы) у Вас должны стоять на тех полях, которые участвуют в условии выборки, т.к. в фильтрации. В вашем конкретном случае, это:
    ON t1.`firma` = t2.`firma` AND t1.`product` = t2.`product`


    то есть, ключи (индексы) должны быть установлены на полях firma и product, при этом, если Вы хотите добиться максимальной скорости при подобной операции - помимо того, что на полях firma и product должны быть проставлены индексы типа KEY - крайне желательно, что бы они были цифрами, т.к. с числами машины работают много быстрее.

    Вообще, у всех объектов, которые Вы вот таким вот образом пытаетесь "склеить" друг с другом, должен быть какой-то уникальный идентификатор, ID, GUID или какой-то другой (на ваш выбор).

    *Касательно именно чисел - зависит от ситуации конечно, в отдельных случаях это могут быть например GUID'ы, крайне желательно, что бы это были НЕ названия фирма, аля "ООО Рога и копыта" и НЕ названия продуктов, вроде "Батон нарезной #1".

    Ну а если всё-таки Вам ну очень хочется использовать именно названия (заголовки) вместо уникальной идентификации каждого объекта, то имейте в виду, что в индекс попадают первые 255 символов. И, индекс по текстовым полям (CHAR/VARCHAR) - и сам по себе будет занимать больше, нежели его числовой аналог, и как следствие будет работать медленнее, нежели бы он был числом (идентификатором объекта).
    Ответ написан
    3 комментария
  • Как правильно спроектировань БД?

    Wolfnsex
    @Wolfnsex Куратор тега Веб-разработка
    Если не хочешь быть первым - не вставай в очередь!
    Есть две таблицы. Таблица с этими товарами и таблица с брендами. Эти две таблицы связаны друг с другом через третью таблицу.

    У вас один товар может иметь сразу несколько брендов?

    Я так понимаю надо сделать таблицу соотношений, где два поля - id_товара и id_его аналога
    Допустим у товара с ID 1 есть три аналога - получается на один товар три записи. А у этого аналога в аналогах - товар с ID 1 и оставшиеся два товара. Уже 6 записей. В общем что то мне такое решение не нравится.

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

    Если же все товары между собой являются абсолютными аналогами друг-друга, есть альтернативный подход. Он заключается в том, что вы создаёте какую-то группу аналогов, например, в таблице analog_groups, каждая запись в которой = 1 группа аналогов. Далее, Вы указываете в товаре, к какой группе аналогов он принадлежит, это можно делать как по ID группы, так и по её заголовку (или любому другому параметру, который Вы к ней добавите) или по параметру id_группы_аналогов у любого другого товара, который в эту группу уже входит.

    Особенности такого подхода:
    а) Отсутствие избыточности данных
    б) Все товары в одной группе аналогов всегда будут аналогами для всех остальных товаров в этой же группе
    в) Нам не нужно будет делать множество одинаковых телодвижений, постоянно перелинковыая аналоги товаров друг у друга
    г) Экономиться место на диске и не раздувается БД
    д) Мы не можем выставить сортировку или приоритеты вывода аналогов для каждого отдельно товара без жестких костылей
    Ответ написан
    5 комментариев
  • Как исправить глюки с SELECT MAX(`id`)?

    Wolfnsex
    @Wolfnsex Куратор тега PHP
    Если не хочешь быть первым - не вставай в очередь!
    Не уверен, что это 100% поможет, не проверял логику работы этой функции, но попробовать стоит:
    SELECT * FROM you_table WHERE id = LAST_INSERT_ID();


    Иначе говоря:
    SELECT LAST_INSERT_ID();

    *Сразу не заметил... Но после с автоинкрементом лишним не будет.
    Ответ написан
    2 комментария
  • Как найти в базе данных сайта WordPress страницу, потенциально зная лишь её заголовок?

    Wolfnsex
    @Wolfnsex
    Если не хочешь быть первым - не вставай в очередь!
    На счёт phpMyAdmin'а не скажу, но Вы легко можете это сделать следующим образом:
    1. Экспортируем базу в SQL-файл
    2. Открываем полученный файл в любом редакторе
    3. Нажимаем Ctrl+F или F3
    4. Вводим искомую строку
    5. Ищем... И если находим - видим ID'шник или какую-то другую информацию, идентицирующую искомую страницу.

    Скорее всего, база довольно небольшая и это легко реализуется.

    Так же, подобный функционал (для реализации поиска по всей БД) есть в множестве программ для работы с БД, например, в HeidiSQL, но, так как Вы пользуетесь phpMyAdmin'ом, могу предположить, что возможности подключить к БД из программы "напрямую" у Вас нет, по этому, предложил выше описанный вариант.
    Ответ написан
    Комментировать
  • Какой запрос выгодней по производительности?

    Wolfnsex
    @Wolfnsex
    Если не хочешь быть первым - не вставай в очередь!
    Всё на самом деле зависит от того, что лично Вы подразумеваете под определением "сильно нагруженный портал" и от многих других факторов, в том числе, от используемого железа, версии MySQL (и/или его форка) и конечных параметров и настроек, и так далее. А так же, от "качества" администратора, которому вверят эту БД.

    Субъективно, оценивая Ваш вопрос, я бы порекомендовал примерно следующее:
    В "интернете", активно практикуется подход кэширования данных, не зависимо от того, какие это данные именно. Кэшируют всё, от отдельных блоков на сайте, до целых страниц вместе с cookie's, картинками и скриптами.

    В пользу кэша говорят многие факторы. Против же кэширования обычно приводятся два основных аргумента:
    а) Лишний расход оперативной памяти и/или жесткого диска
    б) Кэш не стоит применять в тех случаях, когда ресурсозатраты (машинные) на кэширование выше, чем полученный эффект экономии от получения данных из кэша (обычно это те случаи, когда количество циклов записи меньше, или незачительно больше чем количество циклов чтения данных)

    В вашем же случае, кэширование возможно в двух вариантах:
    1. MySQL (в отличии от некоторых других БД) сам кэширует результаты запросов, причем делает он это по умолчанию, но параметры кэширования можно (и чаще всего нужно) настраивать дополнительно
    2. Использование кэша с помощью специально разработанных для этих целей программ, например Redis или Memcached. PHP (и Laravel в т.ч., если мне не изменяет память) отлично дружат с ними.

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

    либо, Вы можете использовать для хранения подобных данных (например, соотношения координат с результатами поиска) либо в таблицы в памяти (в MySQL есть тип таблиц "MEMORY"), либо хранить эти данные в Redis/Memcached/etc, глобально суть не изменится, скорость работы обоих вариантов (Таблицы в памяти vs Redis/Memcached) будет примерно сопоставимой.

    Обновлять данные в хранилище можно на основе событий, реализация которых в достаточной мере присутствуют в Laravel. То есть, вкратце выглядит это так:
    1. Обновляется (добавляется, изменяется) какой-то блок данных, связанный с фирмой, это в свою очередь порождает какое-то событие (одно из событий)
    2. Слушатель событий получает данные и делает соответствующие изменения в кэше данных, таким образом, данные в кэше всегда актуальны (либо рассинхронизация данных довольно мизерная, в пределах примерно секунды) и никакие CRON'ы, которые бестолку будут мучить базу или кэш-хранилище - не нужны.
    Ответ написан
    1 комментарий
  • Как вывести запись из БД?

    Wolfnsex
    @Wolfnsex Куратор тега PHP
    Если не хочешь быть первым - не вставай в очередь!
    В целом Вам уже предложили верное (по крайней мере, логически верное) решение. Но лично я вижу у Вас два ключевых момента:

    1. Зачем Вам получать данные из базы, которые только что, туда же и записали? Тем более, таким, относительно извращенным образом, и тем более в 2 запроса (запрос + вложенный запрос). Если нужно получить последнюю запись из базы, достаточно сделать запрос типа:
    SELECT * FROM table ORDER BY id DESC LIMIT 1;
    Так мы получим последнюю запись, причем не ту, которую мы туда вставили, а ту, которая физически будет последней на момент выполнения запроса, что полностью аналогично Вашему варианту, но в 1 запрос (без подзапросов).

    Есть ещё вариант запроса, в один запрос:
    SELECT * FROM table WHERE id = LAST_INSERT_ID();
    По этому варианту, не могу точно сказать что мы получим, последнюю существующая запись в БД на момент выполнения запроса, или конкретно последнюю вставленную нами запись в БД... но работает он точно не хуже Вашего примера :)

    1.1. Почему бы нам сразу не выводить те данные, которые мы только что записали в БД? Ведь это как раз те же самые данные, которые нам и нужны, но они уже получены.

    2. Обычно, в такой ситуации, приводят вывод var_dump() (или аналогичной функции), что бы понять, почему именно данные не выводятся. А что бы это понять, нужно сначала выяснить, что у нас в переменной вообще... по крайней мере, это может помочь другим разработчикам, а Вы сможете более точно сформулировать вопрос, например, "ожидалось, что в результате будет скалярный тип - а там почему-то курсор результата запроса из БД". То есть,
    <?php
    var_dump($result);
    //вместо
    echo $result;

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

    Wolfnsex
    @Wolfnsex Куратор тега PHP
    Если не хочешь быть первым - не вставай в очередь!
    Всё зависит от того, как построена логика Вашего приложения или сайта. +1 запрос (а скорее даже не запрос, а доп. условие на что-то), вида:
    SELECT IF ((NOW() + INTERVAL 15 DAY) > row_date_value, 'that', 'then') AS result

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

    Но, с другой стороны, контролировать логику работы на уровне БД, пожалуй не самое практичное решение. В 99% случаев, есть более правильные механизмы реализованные на уровне фреймворка, так же как например, авторизация. Вы же не проверяете можно ли пользователю создавать запись новостей на сайте, на уровне БД?

    В частности, в зависимости от системы/фреймворка, подобная логика проверок и валидаций обычно встроена и оптимальным решением будет использовать именно её (как именно она устроена, можно посмотреть на примере модуля авторизации Вашей системы).

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

    Если вопрос состоит в том, как лучше сверять даты на уровне "контроллера" (или чего-то ему аналогичного) - Вы можете перевести дату в число Unix-timestamp и сравнивать два числа, быстро и удобно.
    Ответ написан
    Комментировать
  • Поиск в MySQL игнорируя HTML-теги?

    Wolfnsex
    @Wolfnsex Куратор тега HTML
    Если не хочешь быть первым - не вставай в очередь!
    Вы можете попробовать делать поиск с помощью регулярных выражений, отфильтровывая теги, но сам по себе поиск типа LIKE/ILIKE - не самая быстрая операция для БД, а поиск по регулярке, может значительно усугубить показатели производительности. Вариант, который Вам предложили выше, более оптимальный и в целом похожие решения не редко применяются на практике (когда модифицированный текст, специально подготовленный для поиска по нему, хранится отдельно, в т.ч. в специально отведенной колонке).
    Ответ написан
    Комментировать
  • Как вывести номер строки но не id?

    Wolfnsex
    @Wolfnsex Куратор тега PHP
    Если не хочешь быть первым - не вставай в очередь!
    $count++; // нужно ставить перед $res_array
    $res_array[$count] = $row;

    Вот эту строку можно сократить до
    $res_array[] = $row;

    PHP сам пронумерует индексы массива, начиная с нуля и выше, соответственно. Единственное, что меня смущает, переменные $res_array и $count не объявлены до их использования.

    Далее, Вы можете выводить слайды с их номерами, основываясь на индексе массива, или без него (если индексы не числовые или их нумерация сбита), одним из вариантов:

    1. По индексу (ключу) массива:
    foreach($res_array as $k => $v) {
        print $k.'<br/>'; //Ключ (индекс) массива
    }


    2. Игнорируя индекс (ключ) массива:
    for($i = 0; $i < count($res_array); $i++) {
        print $i; //индекс
    }


    Вы так же можете модифицировать примеры для своего удобства, если нужна нумерация, например с единицы.
    Ответ написан
    Комментировать