Задать вопрос
Ответы пользователя по тегу MySQL
  • Какой стэк использовать для быстрого доступа данных?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Для "доступа" использовать ту реляционную БД, которая имеется в наличии. При появлении проблем с производительностью - диагностировать их, и с конкретными вопросами приходить на Хабр.
    Для поиска - "быстрого", "по параметрам", полнотекстового - использовать предназначенный для этого движок, например Эластик. При появлении проблем с производительностью - диагностировать их, и с конкретными вопросами приходить на Хабр.

    spoiler
    Сам по себе ход мысли в вопросе очень характерный.
    Звучит примерно так: "Купил машину, что-то плохо тянуть стала. Думаю докупить упряжку лошадей, чтобы запрягать спереди. Лошадиные силы ведь прибавятся! Посматриваю ещё на воздушных змеев, лыжи, и дополнительный омыватель". То есть вместо простых и очевидных действий по диагностике, формулированию конкретных проблем, и последующему ремонту машины мы фантазируем себе набор каких-то бессмысленных и хаотичных телодвижений. Которые мало того что вообще никак не помогут, но скорее всего ухудшат ситуацию.

    И, разумеется, не приводим ни одной цифры, ни одного конкретного примера. Ни даже примерной нагрузки на систему - хоть в попугаях/посетителях. Ни загрузки процессора на серверах. Ни причин, по которым пришлось делать мастер-слейв. Ни текущей статистики по Mysql. Одни оценочные суждения, " А здоровье мое не очень. То лапы ломит, то хвост отваливается." Общие причитания про повышение нагрузки, "на запись и чтение". При том что запись уже больше не упоминается нигде, и непонятно - есть какие-то проблемы с ней, или нет. Да и с MySQL в целом.

    В итоге из всех невнятных жалоб становится понятно, что с самой БД, судя по всему, проблем нет. А есть только один участок, к которому есть вопросы - поиск. Есть идея реализовать его через Эластик, но есть сомнения. При том что Озон там, МВидео и прочих мастодонтов Эластик устраивает, а вот нашему магазинчику с 300К записей он не угодил. Сразу вспоминается анекдот про нового русского и 600-й мерс с засорившейся пепельницей. Не тянет Эластик? Будем менять на Монгу!

    Я думаю, что в таких ситуациях в первую очередь надо установить в систему здравый смысл. Перестать метаться с безумными фантазиями, а подойти к вопросу логически: есть вопросы к поиску? Значит надо поставить поисковый движок. поисковый движок - это в 99% случаев - Эластик. К нему есть вопросы? Отлично. Максимально подробно формулируем эти вопросы - не забывая привести индексы, конфиги, запросы - и задаём конкретный вопрос по оптимизации работы Эластика.

    А сейчас проблема "может мне монгу воткнуть?" проходит исключительно по разряду "Когда коту делать нечего, он гигиеной занимается".


    P.S. Не удивлюсь, если в итоге выяснится, что вся проблема сводится к истории, которая случилась в одном маленьком интернет-магазинчике: там тоже купили аж 3 сервера по 256Г мозгов в каждом, мастер-слейв, все дела... И не поменяли дефолтное значение innodb_buffer_pool_size в 128М. И что характерно, этот "кластер" даже тащил какое-то время, пока не случилась 10х нагрузка.
    Ответ написан
    2 комментария
  • Почему данные заказа не отправляются в базу данных?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Потому что вы вообще никак не отреагировали на те ответы, которые вам дали в прошлый раз на этот же самый вопрос.
    Вам написали, как правильно выполнять запросы. Вы это сделали?
    Вам написали, какие действия выполнять, если код не работает. Вы их выполнили?
    Вы так и планируете ходить на Хабр каждый раз, когда код не работает? Вот прямо серьёзно? Это, по-вашему, именно то, чем занимаются программисты?

    Пожалуйста, прочитайте ответы, которые вам давали на этот вопрос в прошлый раз и начните уже им следовать.
    Иначе программирование для вас так и останется игрой в прятки в темноте - "ой, что-то написала, не работает! Ой, что-то другое написала - работает!".

    К тому что написано в предыдущем ответе надо добавить только одно: перед
    new mysqli(...);
    надо всегда писать
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    чтобы база данных сама сообщала, почему не может выполнить запрос. Если дело именно в нём.
    Ответ написан
  • Как правильно объединить два запроса в один?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Правильно будет не объединять запросы в один без необходимости.
    Ответ написан
  • Как сделать так, что бы при пустом запросе в базу выводились ВСЕ значения?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    есть немного замороченный способ, но в целом он требует куда меньше кода
    WHERE (account_id=? OR ? is null)  AND (priority=? OR  ? is null)

    Чтобы его использовать, надо всего лишь передавать каждую переменную в запрос по два раза (и следить, чтобы пустые переменные содержали null).

    Другим вариантом является условная сборка запроса.
    Для этого мы собираем условия и переменные для них в массивы

    $conditions = [];
    $parameters = [];
    if ($account_id)
    {
        $conditions[] = 'account_id=?';
        $parameters[] = $account_id;
    }
    if ($priority )
    {
        $conditions[] = 'priority =?';
        $parameters[] = $priority;
    }

    собираем из условий запрос и выполняем его, привязывая все переменные разом
    тут из сложного будет привязка переменных из массива, но благодаря оператору распаковки аргументов это не так уж и сложно.
    if ($parameters)
    {
        $sql .= " WHERE ".implode(" AND ", $conditions);    
        $stmt = $db->prepare($sql);
        $stmt->bind_param(str_repeat("s", count($parameters)), ...$parameters);
        $stmt->execute();
        $result = $stmt->get_result();
    } else {
        $restult = $db->query($sql);
    }
    Ответ написан
    3 комментария
  • Как вытащить данные из stmt?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    вместо store_result(); надо писать get_result();
    этот метод даст вам привычный ресурс, из которого уже можно получить данные обычным способом
    $stmt = $link->prepare("SELECT * FROM users WHERE id=?");
    $stmt->bind_param('i', $value);
    $stmt->execute();
    $result = $stmt->get_result();
    $row = $result->fetch_assoc();
    Ответ написан
    5 комментариев
  • В чём ошибка подключения к безе по PDO?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ошибку указывает сама PDO.
    Для этого в настройках надо указать PDO::ERRMODE_EXCEPTION - это уже сделано.
    После этого, в случае, если выполнение запроса завершится ошибкой, РНР об этом сообщит.
    Надо только, опять же, не забыть включить отображение (на домашнем компьютере) или логирование (на боевом сервере) ошибок РНР.

    Если же РНР никаких ошибок не выводит, то их и нет.
    Ответ написан
    4 комментария
  • Что нужно отправить на сервер, чтобы php понял это, как null?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вопрос неверный. В стиле анекдота "у таракана уши в ногах".
    Разумеется, сервер всё прекрасно видит.
    чтобы РНР принял null, надо отправить на сервер null. Удивительно, но факт.
    var_dump(json_decode('{ 
        "name": ["i", "b"], 
        "val": [null]
    }',1));


    А вот что там делает код на этом сервере - никто не знает.
    И обращаться надо к автору кода. А не в Спортлото

    Скорее всего там либо array_filter, либо isset/empty($array['val']);
    Ответ написан
    4 комментария
  • Как получить список таблиц и полей без индекса (mysql), по которым происходит выбор?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Джинны и феи бывают только в сказках, дружок.

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

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Сначала я вообще ничего не понял, но поразмыслив, разобрался, про что этот вопрос.
    И поскольку он повторяет весьма распространённые заблуждения, то будет полезно на него подробно ответить.

    Можно ли как-то безопасно сделать такой запрос, который я соберу в строку?

    Нет, нельзя.

    Это распространённое, но очень смешное заблуждение. Если подумать, то само по себе prepare() ни от чего не защищает. Это не волшебное слово типа "Экспекто патронум!" - написал, и дальше уже можно не париться, оно само как-то магически защитит от инъекций. В реальной жизни таких слов ещё, увы, не придумали. А защищает именно замена актуальных переменных в запросе на знаки подстановки и последующая привязка через bind_param. А prepare просто говорит базе данных ,что запрос еще рано исполнять, это только схема запроса, а данные для него приедут позже.

    Я так понял, что если я выполняю $sql = $mysqli->prepare($request), то выполнится только один запрос, который первый, даже, если в него вложен будет второй, пусть я его строкой и засунул.

    Это тоже очень распространённое, и очень вредное заблуждение. Запрос выполнится только один, да. Тут всё верно. Но проблема в том, что SQL инъекция - это не один запрос
    INSERT INTO students (name) VALUES ('Robert');DROP TABLE students;
    , который рисуют в примерах для первоклассников. Инъекция - это любой посторонний код в запросе, вообще любой.

    Поэтому собирать в строку надо всё равно запрос со знаками подстановки, а потом его выполнить. Благо, в 5.6 версии пхп появился оператор распаковки параметров, который значительно облегчил эту задачу.

    Не хочется использовать лишние переменные и обработку для типов данных

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

    Для запроса, который приведен в примере, код будет относительно простым, поскольку заменяется на вызов IN:

    $names = ["Stepan" , "Stiv"];
    $in    = str_repeat('?,', count($names) - 1) . '?'; // получаем строку вида "?,?"
    $sql   = "SELECT * FROM users WHERE name IN ($in)"; // поставляем её в SQL
    $stmt  = $mysqli->prepare($sql); // prepare
    $types = str_repeat('s', count($names)); // получаем строку "sss" по количеству переменных
    $stmt->bind_param($types, ...$names); // привязываем наш массив
    $stmt->execute(); // выполняем
    $result = $stmt->get_result(); // дальше всё как обычно
    $data = $result->fetch_all(MYSQLI_ASSOC);


    Для более сложных запросов принцип будет тот же: собираем строку с плейсхолдерами, а переменные для неё - в массив. И потом выполняем так же через bind_param($types, ...$parameters);, как-то так:

    $conditions = [];
    $parameters = [];
    if (!empty($_GET['name']))
    {
        $conditions[] = 'name LIKE ?';
        $parameters[] = '%'.$_GET['name']."%";
    }
    // любое количество таких условий
    if ($conditions)
    {
        $sql .= " WHERE ".implode(" AND ", $conditions);
    }

    и дальше выполняем обычным порядком.

    Ну и в завершение, ответим на вопрос из заголовка буквально
    Как сделать prepare запрос без bind_params?

    Как правильно заметил TheAndrey7 в комментариях, начиная с версии 8.1 можно будет отправить переменные сразу в execute():

    $names = ["Stepan" , "Stiv"];
    $in    = str_repeat('?,', count($names) - 1) . '?';
    $sql   = "SELECT * FROM users WHERE name IN ($in)";
    $stmt  = $mysqli->prepare($sql); 
    $stmt->execute($names); 
    $data = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
    Ответ написан
    4 комментария
  • Как убить ошибку Error Code: 1114. The table '...\#sqlc60_9_37' is full?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    alter table test add key (sec_code, class_code)
    и смотреть, уйдёт ли temporary из поля Extra в EXPLAIN

    И вообще - в первую очередь смотреть EXPLAIN, а не возиться с этой ерундой.
    и убирать using temporary ДО того как временной таблице перестанет хватать места на диске.
    Потому что у меня даже и без этой ошибки инфаркт будет, если я увижу такой запрос в продакшен коде.
    Ответ написан
    3 комментария
  • Как связать новость на одной странице с ее развернутой формой на другой?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Поднимаем глаза наверх. Только не к Небу, а чуть ниже. К адресной строке своего браузера (пока она ещё там есть, и её не отменили улучшаторы из компании альфабет).
    И - о чудо! - видим там ссылку вида qna.habr.com/q/1077518
    Казалось бы, что могут означать эти загадочные цифры?.. ;-)
    spoiler

    Для "моего первого скрипта на пхп" правда там будет не /q/1077518, а news.php?id=1077518.
    После чего в скрипте news.php вожделенное число будет доступно в переменной $_GET['id']
    Содержимое которой можно будет использовать для запроса строки из БД.
    Только не так как это показано во всех видео на ютубе, а нормально:

    $query = "SELECT * FROM news WHERE id=?";
    $stmt = $conn->prepare($query);
    $stmt->bind_param("s", $_GET['id']);
    $stmt->execute();
    $result = $stmt->get_result();
    $row = $result->fetch_assoc();


    в переменной $row будет содержимое нужной строки из БД


    А так-то вопрос, конечно, про SQL ;-)
    Ответ написан
    Комментировать
  • Как корректно реализовать автовход пользователя на сайт?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Очень правильный вопрос. Разумеется, с таким подходом зайдет кто угодно.

    поэтому надо в таблицу users добавить поле autoenter, и если пользователь выбирает автологин, то в него записывать значение bin2hex(random_bytes(16)); и его же записывать в куку.
    Ответ написан
  • Как сделать дамп большой базы данных?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ответ написан
    Комментировать
  • Хранение значений массива в БД?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Это задание, а не вопрос.
    Ответ написан
    5 комментариев
  • Как правильно составить запрос к БД?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Стандартный способ:
    SELECT count(*) FROM shop LEFT JOIN shopData ON shopData.shop_id=shop.id WHERE shopData.shop_id IS NULL

    Но следующий способ должен быть быстрее
    SELECT count(*) FROM shop WHERE NOT EXISTS (SELECT 1 FROM shopData WHERE shop_id=shop.id)
    Ответ написан
    2 комментария
  • Как сделать запрос через тройную связь, при это получая все связанные значения 3 таблицы в массив к 1 записи?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    GROUP_CONCAT()
    Но это редко бывает полезно поскольку обычно нужны не только названия ролей, но и их идентификаторы
    Если хочется "одной строчкой", то надо осваивать продвинутые ORM типа Doctrine
    Ответ написан
    Комментировать
  • Как перебрать все значения строки разделенные запятой в mysql?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    В бд не должно быть строк, которые содержат значения, разделенные запятой. Для этого в бд есть таблицы и строки.

    И тогда вопроса как прочитать значение никогда не возникнет
    Ответ написан
    4 комментария
  • Сколько времени должен занимать такой запрос MySQL?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Я не очень понимаю во всех этих AWS, но расход памяти в три гига - это какая-то чушь.

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

    Вообще цифры странные. Полное ощущение что индекс не влезает в память и идёт постоянная работа с диском. Но тогда должен процессор зашкаливать. А он на 5 процентах. Вот не понимаю я эти ваши авс.
    Ответ написан
  • Почему в базу записываются иероглифы?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Хрестоматийный пример того, как не надо задавать вопросы.

    "Я там что-то сделал, получилось каля-маля. Колеса в разный цвет красил. Не помогает".

    Буквальный ответ на вопрос из заголовка: потому что кодировка данных не совпадает с той, которую ждёт база.
    Ответ написан
    Комментировать
  • Как перейти с mysql на elasticsearch?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Никак. "перейти" с базы данных на поисковый движок нельзя.
    Можно сделать поисковый сервис, который будет индексировать информацию, взятую из бд

    На основе этого сервиса сделать полнотекстовый и фасетный поиск.
    А текущую базу данных оставить как есть. Только запросы оптимизировать, чтобы "скорость работы не понижалась"
    Ответ написан
    3 комментария