Мысли о выполнении SQL-запросов

carte_noire

Новичок
Здравствуйте.
Сегодня я писал код, который получал данные из mySQL, представлял их в виде массива. Казалось бы все так обычно.
Потом я смотрел эти данные и менял их, в общем обрабатывал как-то. А после этого мне нужно было сохранить их обратно. То есть сделать UPDATE. И вот я задумался, а как? Быдлокодерская сущность подсказывала:
PHP:
//Псведокод
foreach($items as $item) {
  query(UPDATE table SET column_1=$item['some_value'] WHERE id=$item['elem_id']);
}
Но у меня 100 элементов. Это получается 100 апдейтов. И я подумал, что может быть есть способ сериализовать массив, засунуть его в строку и передать на сервер, а там распаковать его и провести какие-то действия. То есть как бы выполнить такой запрос, который сам скомбинирует пары id->value и выполнит нужный запрос, только инкапсулировать все это на сервере, понимаете?
То есть выполнить всего один запрос вида:
Код:
UPDATE table SET array('value') WHERE id=array('id')
Понимаете?
 

carte_noire

Новичок
Ну да, это то, что я искал...
Так и напишем
Код:
multi(UPDATE $item[1]; UPDATE $item[2]; .... UPDATE $item[10000];)
Вы не поняли. Я хочу как-то накладывать программные структуры данных на SQL. Это что-то вроде ORM-a, только реализацию я хочу вынести в SQL-сервер. Хранимая процедура? Дайте еще умных слов....
 

Фанат

oncle terrible
Команда форума
Для начала определись, чего ты хочешь.
А то тебя, как щеночка на льду, сразу во все стороны тянет. И хранимые процедуры тебе хочется, и запросов сэкономить, и орм (при этом остаётся загадкой - что именно ты собираешься мапить и куда, этим своим мультизапросом).

Для начала ответь себе на вопрос, чем плох быдлокодерский вариант.
 

carte_noire

Новичок
Для начала ответь себе на вопрос, чем плох быдлокодерский вариант.
Вот! Я тоже себе так говорю... По сути, все так делают и ничего - живы, здоровы...
Но в последнее время мне кажется, что многое из того, что я делаю на PHP - тупо и банально.
Недавно писал парсер, который запускался по крону и сохранял распарсенное в текстовый файл для ускорения загрузки страницы... Кэш такой своеобразный получился...
Все довольны, а мне кажется, что там говнокод... Перевел все на классы для успокоения... Так теперь кажется, что у меня быдло-ООП... И я перевел на классы просто ради перевода на классы, но все при этом осталось так же, только ф-ии вызываются через "->". Тупо обертку написал...
Но плюс все-таки появился, я обеспечил "гранулярность"(из книжки по алгоритмам) программы, то есть разбил ее на слабосвязанные части, которые выполняются друг за другом. Вначале выполняешь все HTTP-запросы для получения сырого контента, потом парсишь весь контент и формируешь из него структуры языка, в общем конвейер такой..

О чем это я? Ах да...
На фоне того, что 100 UPDATE-ов в цикле это тупо и скучно я решил узнать, как можно за 1 запрос записать массив значений. То есть передать в MySQL не строки, а массив строк. А обработку этого массива строка возложить на mysql-daemon.
Сегодня мне пришла хорошая аналогия - то, что я хочу, можно описать как векторный процессор (http://ru.wikipedia.org/wiki/Векторный_процессор).

Он может выполнять однотипные операции с векторами за 1 команду. Ведь по сути, действия в цикле они однотипны. Просто меняется значения и все.
Вот я и хочу оперировать с массивами... То есть создать такую абстракцию, что бы дать в запрос два массива вида id => value. А сервер уже сам с ними разбирается и сопоставляет одно к другому.
Надеюсь, все поняли, о чем я...
UPD.
Разумеется, в запросах мы можем оперировать только строками, поэтому предварительно структуры языка нужно сериализовать... Думаю JSON подойдет... Главное, что бы потом из этого JSONа можно было получить исходные структуры на mysql-сервере...
 
Последнее редактирование:

Linker

Новичок
carte_noire, есть ещё вариант: DELETE + INSERT в одной транзакции, при условии, что в запросе DELETE все строки группируются по какому-нибудь признаку (внешний ключ, например, или общее значение в специальном поле), а INSERT будет "собран" в цикле и представлять из себя один запрос. Первым запросом сбросятся все "устаревшие" записи, вторым запросом вставятся "обновлённые" записи.
 

fixxxer

К.О.
Партнер клуба
Возможно, тут подойдет insert (), () ... on duplicate key update field1 = VALUES.field1, field2 = VALUES.field2
 

carte_noire

Новичок
@AmdY , да у меня не такие большие познания в SQL... Ладно...
"Надо уметь находить информацию, что бы не задавать глупых вопросов". Всем мир, всем спасибо... Шлак этот потрите нафиг.
 

Фанат

oncle terrible
Команда форума
На фоне того, что 100 UPDATE-ов в цикле это тупо и скучно я решил узнать, как можно за 1 запрос записать массив значений. То есть передать в MySQL не строки, а массив строк. А обработку этого массива строка возложить на mysql-daemon.
Стандартного способа нету. Есть только есть только нестандартные хаки, которые ничего не дадут в плане производительности, кроме чувства глубокого удовлетворения
 
Последнее редактирование:

carte_noire

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

##Ушел пить чай##
 
  • Like
Реакции: AmdY

Фанат

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

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

Но вообще, SQL - по факту атомарный язык. И я бы на твоём месте не занимался преждевременной оптимизацией, а сделал поддержку единственного апдейта, а для множественных завернул их в цикл и транзакцию.
 

carte_noire

Новичок
PHP:
foreach($res as $item) {
   $sql = "UPDATE `posts` SET `post_content`='". $change_post ."' WHERE `ID`='".$item['ID']."'";
   $dbh->query($sql);
}
Вот мой код. Адекватно? Задача была такая - выбрать все страницы и заменить в них ссылки (<a></a>) по шаблону.
Я их выбрал, заменил контент... Теперь вот так записываю обратно.
Ну вот тут ко мне и пришла эта мысль про один супер-запрос, который без цикла все сделает.
 

AnrDaemon

Продвинутый новичок
Неадекватно. Судя по всему, используется PDO, так, простите, и используйте уже его, а не доморощенные "конструкторы" запросов из обрезков строк.
prepare запроса перед циклом, execute в цикле. Реально выиграть от 2% до 10% времени CPU, в зависимости от количества вставляемых данных.
 
Сверху