CASE производительность в MySQL? - PullRequest
5 голосов
/ 11 октября 2011

Интересно, если использовать выражение CASE ... WHEN ... THEN в запросах MySQL
оказывает негативное влияние на производительность?

Вместо использования выражения CASE (например, внутри запроса UPDATE)
у вас всегда есть возможность сделать заявление if else в вашей программе
написанный на php, python, perl, java, ... для выбора запроса для отправки, например (в псевдокоде):

prepareStatement(
"UPDATE t1 SET c1=c1+1, msg=CASE (@v:=?) WHEN '' THEN msg ELSE @v END"
);
setStatementParameter(1, message);

или инсад:

if (message == "") {
    prepareStatement("UPDATE t1 SET c1=c1+1");
} else {
    prepareStatement("UPDATE t1 SET c1=c1+1, msg=?");
    setStatementParameter(1, message);
}

(c1 здесь нужен только для того, чтобы показать, что что-то происходит в обоих случаях)

Какой способ сделать это имеет лучшую производительность?
А сколько стоит потеря производительности?

1 Ответ

12 голосов
/ 11 октября 2011

Все функции для каждой строки будут влиять на производительность. Единственный реальный вопрос: «Достаточно ли мало влияние, чтобы о нем не беспокоиться?». Это то, что вы должны обнаружить, измеряя, а не угадывая. Администрирование базы данных - это занятие «забей и забудь», если ни ваши данные, ни ваши запросы никогда не изменятся.

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

Под "достаточно маленьким" в приведенных выше комментариях я имею в виду, что вам, вероятно, не нужно беспокоиться о влиянии производительности на что-то вроде:

select * from friends where lowercase(lastname) = "smith"

если у вас только трое друзей.

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

select name from customers where lowercase(name) like '%comp%'

Это, вероятно, обрушит на вас ваших администраторов базы данных, как тонну кирпичей.

Один способ, которым мы исправили это в прошлом, - это ввести избыточность в данные. Используя этот первый пример, мы добавили бы дополнительный столбец с именем lowerlastname и заполнили бы его строчными буквами lastname. Индекс, который для целей поиска и ваших операторов select становится ослепительно быстрым, как и должно быть.

И что это делает с нашим любимым 3NF, я слышал, вы спрашиваете? Ответ - ничего, если вы знаете, что делаете: -)

Вы можете настроить базу данных таким образом, чтобы этот новый столбец заполнялся триггером вставки / обновления для обеспечения согласованности данных. Совершенно допустимо ломать 3NF по соображениям производительности, если вы понимаете и смягчаете последствия.

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

Поскольку большинство баз данных читаются гораздо чаще, чем пишутся, это переносит стоимость вычисления на вставку / обновление, эффективно амортизируя ее во всех операциях выбора. Тогда запрос будет:

select name from customers where name_contains_comp = 'Y'

Опять же, вы обнаружите, что запрос ошеломительно быстр, за небольшую плату за несколько более медленные вставки и обновления.

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