Обновление нескольких строк в одном запросе очень низкая производительность - PullRequest
2 голосов
/ 27 сентября 2011

Я ищу лучший способ обновить несколько строк одновременно одним запросом. В настоящее время у меня есть:

UPDATE `profiles` SET `name` = CASE `id` WHEN 1 THEN 'John' WHEN 2 THEN 'Jane' END, `gender` = CASE `id` WHEN 1 THEN 'Male' WHEN 2 THEN 'Female' END WHERE `id`=1 OR `id`=2

но это занимает около 4 минут (мой реальный запрос по 10 полям в базе данных из 20 миллионов строк), в отличие от отдельных запросов на обновление, которые занимают около 1 секунды.

Я пытаюсь понять, почему, что на самом деле происходит? Я подумал, что, указав идентификатор в предложении WHERE, это ускорит его.

Ответы [ 3 ]

0 голосов
/ 27 сентября 2011

Не могли бы вы опубликовать DDL для таблицы профилей, пожалуйста?Это поможет увидеть, какие типы индексов вы настроили (например, можем ли мы предположить, что столбец id является первичным ключом здесь?).Если вы используете MySQL, просто запустите 'SHOW CREATE TABLE profile', чтобы сгенерировать DDL.

Несколько моментов, которые могут помочь:

1) Попробуйте использовать BETWEEN в своем WHERE.предложение вместо ИЛИ.например, UPDATE profiles

SET `name` = 

CASE `id` WHEN 1 THEN 'John' 

WHEN 2 THEN 'Jane' END, 

`gender` = CASE `id` 

WHEN 1 THEN 'Male' WHEN 2 THEN 'Female' END 

WHERE `id` between 1 and 2;

2) Попробуйте разбить запрос на отдельные запросы, чтобы избежать использования оператора CASE, например,

update `profiles`

set `name` = 'John',

    `gender` = 'Male'

where `id` = 1;

и

update `profiles`

set `name` = 'Jane',

    `gender` = 'Female'

where `id` = 2;

Iне знаю, возможно ли это, так как я не уверен, в каком контексте вы используете запрос!Надеюсь, это поможет.

0 голосов
/ 27 сентября 2011

Можете ли вы указать все ваши дела для всех полей, поэтому у нас есть идея получше.Если у вас есть фиксированный регистр для обновления только для id = 1 и 2, тогда разбейте ваш запрос на 2 запроса, например:

update `profiles` set `name` = 'John', `gender` = 'Male' where `id` = 1; 
update `profiles` set `name` = 'Jane', `gender` = 'Female' where `id` = 2; 
0 голосов
/ 27 сентября 2011

У вас есть индекс по id? Если нет, то это хорошая идея для ее создания (Внимание, это может занять много времени, делайте это в непиковые часы):

CREATE INDEX id_idx ON profiles (id);

Кстати, запрос по 10 полям с 20 миллионами строк в таблице может занять много времени, особенно если индексов нет или кэш холодный.

Обновление: для тестирования и из-за любопытства я попытался воспроизвести вашу ситуацию. Для этого я составил несколько тестовых данных.

DDL: https://gist.github.com/b76ab1c1a9d0ea071965
Запрос на обновление: https://gist.github.com/a8841731cb9aa5d8aa26
Скрипт Perl для заполнения таблицы тестовыми данными: https://gist.github.com/958de0d848c01090cb9d

Однако, как я уже упоминал в своем комментарии ниже, Mysql не позволит вам вставить дубликаты данных, потому что id - это ваш ПЕРВИЧНЫЙ КЛЮЧ, но не уникальный. Если бы вы могли прокомментировать схему таблицы и / или опубликовать свой DDL, это очень помогло бы.

Удачи! Алекс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...