Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Оптимизация UPDATE ... SELECT? / 10 сообщений из 10, страница 1 из 1
25.01.2014, 02:48:10
    #38537534
OlegROA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация UPDATE ... SELECT?
Добрый день, коллеги!

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

Задача - периодически корректировать значение в этом поле.
Планирую использовать такой запрос
Код: sql
1.
2.
3.
4.
5.
6.
update members as mem
  set mem.exp_istree = (
      select mov.total*mov.price from moves as mov
      where mov.member_ndx = mem.id
      group by mov.member_ndx
  )


Вопрос первый - насколько оптимален такой запрос и если не оптимален - какие есть варианты его реализации?
Вопрос второй - будет ли сервер неявно блокировать таблицы клиентов и продаж или только изменяемые записи или вообще не будет ничего блокировать?

Спасибо!
...
Рейтинг: 0 / 0
25.01.2014, 02:51:21
    #38537535
OlegROA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация UPDATE ... SELECT?
В догонку - в таблице moves есть необходимый ключ по продажам клиента. Explain показывает, что именно этот ключ и будет использоваться для селекта.
...
Рейтинг: 0 / 0
25.01.2014, 07:03:53
    #38537553
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация UPDATE ... SELECT?
OlegROA,

может там все же SUM добавить?


ddl таблиц давай.
...
Рейтинг: 0 / 0
25.01.2014, 22:38:47
    #38537925
OlegROA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация UPDATE ... SELECT?
MasterZivOlegROA,
может там все же SUM добавить?
ddl таблиц давай.Прошу прощения - да, естественно, там SUM используется.
И исходное задание я немного упростил - надо не одно поле а сразу два изменять этим запросом.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
CREATE TABLE `members` (
  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `Sum1` decimal(11,2) DEFAULT NULL,
  `Sum2` decimal(11,2) DEFAULT NULL,
  PRIMARY KEY (`Id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `moves` (
  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `DATE` date NOT NULL,
  `Member_Ndx` int(10) unsigned NOT NULL,
  `Total` decimal(11,3) DEFAULT '0.000',
  `Price1` decimal(11,2) DEFAULT '0.00',
  `Price2` decimal(11,2) DEFAULT '0.00',
  PRIMARY KEY (`Id`),
  UNIQUE KEY `MemCard_Key` (`Member_Ndx`,`DATE`,`Id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Для обновления одного поля, имхо, подходит запрос:
Код: sql
1.
2.
3.
4.
5.
6.
UPDATE members AS mem
  SET mem.sum1 = (
      SELECT SUM(mov.total*mov.price1) FROM moves AS mov
      WHERE mov.member_ndx = mem.id
      GROUP BY mov.member_ndx
  )

Как бы в этот запрос добавить обновление второго поля mem.sum2, что-бы его значение подсчитывалось в том-же селекте?
Что-то типа:
Код: sql
1.
2.
3.
4.
5.
6.
UPDATE members AS mem
  SET mem.sum1, mem.sum2 = (
      SELECT SUM(mov.total*mov.price1), SUM(mov.total*mov.price2) FROM moves AS mov
      WHERE mov.member_ndx = mem.id
      GROUP BY mov.member_ndx
  )
...
Рейтинг: 0 / 0
25.01.2014, 23:03:07
    #38537938
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация UPDATE ... SELECT?
OlegROAКак бы в этот запрос добавить обновление второго поля mem.sum2, что-бы его значение подсчитывалось в том-же селекте?
Что-то типа:
Код: sql
1.
2.
3.
4.
5.
6.
UPDATE members AS mem
  SET mem.sum1, mem.sum2 = (
      SELECT SUM(mov.total*mov.price1), SUM(mov.total*mov.price2) FROM moves AS mov
      WHERE mov.member_ndx = mem.id
      GROUP BY mov.member_ndx
  )


Когда ж уже маны начнут читать ниже первой строки... до многотабличного апдейта - не дочитал, что ли?

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
UPDATE 
  members AS mem
, (
      SELECT
        mov.member_ndx
      , SUM(mov.total*mov.price1) sum1
      , SUM(mov.total*mov.price2) sum2
      FROM moves AS mov
      GROUP BY mov.member_ndx
  ) sq
SET
  mem.sum1 = sq.sum1
, mem.sum2 = sq.sum2
WHERE 
  sq.member_ndx = mem.id
...
Рейтинг: 0 / 0
25.01.2014, 23:48:53
    #38537954
OlegROA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация UPDATE ... SELECT?
AkinaКогда ж уже маны начнут читать ниже первой строки... до многотабличного апдейта - не дочитал, что ли?Дочитал и даже несколько раз перечитывал!
Но я не додумался, что в качестве одной из таблиц может выступать не физическая таблица, а простая выборка!
Хотя последний пример из доки, где заданы две таблицы, но изменяется колонка только первой, должен был натолкнуть на нужную мысль!

Спасибо, большое!!!
...
Рейтинг: 0 / 0
26.01.2014, 06:54:50
    #38538010
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация UPDATE ... SELECT?
OlegROAНо я не додумался, что в качестве одной из таблиц может выступать не физическая таблица, а простая выборка!читаем этоавтор table_references and where_condition are is specified as described in Section 13.2.8, “SELECT Syntax”.идём по ссылке, читаем это:авторtable_references indicates the table or tables from which to retrieve rows. Its syntax is described in Section 13.2.8.2, “JOIN Syntax”.ещё раз идём по ссылке и вкуриваем написанное там :)
...
Рейтинг: 0 / 0
26.01.2014, 14:34:04
    #38538224
OlegROA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация UPDATE ... SELECT?
Кстати, еще вопрос по последнему варианту кода от Akin`ы - для ограничения пересчета только по одному клиенту, добавил в селект по moves условие просмотра продаж по этому клиенту и это же условие добавил в последний where по update
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
UPDATE members AS mem,
  (
      SELECT
        mov.member_ndx
      , SUM(mov.total*mov.price1) sum1
      , SUM(mov.total*mov.price2) sum2
      FROM moves AS mov
      WHERE mov.member_ndx = 1001
      GROUP BY mov.member_ndx
  ) sq
SET
  mem.sum1 = sq.sum1, mem.sum2 = sq.sum2
WHERE 
  (mem.id = 1001) AND (sq.member_ndx = mem.id)


Константа 1001 в данном случае используется для тестирования.
Так вот, explain по такому запросу выдает:
'id''select_type''table''type''possible_keys''key''key_len''ref''rows''extra''1' 'PRIMARY' 'mem' 'const' 'PRIMARY' 'PRIMARY' '4' 'const' '1' NULL'1' 'PRIMARY' '<derived2>' 'ref' '<auto_key0>' '<auto_key0>' '4' 'const' '10' NULL'2' 'DERIVED' 'mov' 'ref' 'MemCard_Key' 'MemCard_Key' '4' 'const' '572' NULL
Интересует вторая строка - какие 10 строк сервер собирается по этому подзапросу выбирать?
Ведь селект вернет только одну строку с итогами по клиенту 1001 и в таблице members тоже только одна запись по клиенту 1001!
...
Рейтинг: 0 / 0
26.01.2014, 14:38:06
    #38538230
OlegROA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация UPDATE ... SELECT?
Отрабатывает, кстати, последний запрос правильно.
...
Рейтинг: 0 / 0
26.01.2014, 22:17:39
    #38538484
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация UPDATE ... SELECT?
OlegROAкакие 10 строк сервер собирается по этому подзапросу выбирать?Да кто ж его знает... а с чего ты решил, что он собирается выбрать именно 10 строк? просто ещё без обращения к данным на основе статистики серверу показалось, что придётся выбрать 10... реально на самом деле выберется 1... ну и что? невеликая ошибка-то, это ж не на полтаблицы мимо. Запусти аналайз - значения авось и поменяются.
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Оптимизация UPDATE ... SELECT? / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]