SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 24.04.2007 16:58:07

anky
Участник
Откуда: Киев
Зарегистрирован: 17.04.2007
Сообщений: 12

limit'ы для PK и U-индексов

еще вопросец smile

в теории (моей теорииsmile), при работе с процедуркой, а в особенности при необходимости сделать проверочный запрос на существование какого-либо значения по первичному ключу, стоит делать так:

if exists(SELECT 1 FROM `some_table` t WHERE t.`id` = _id LIMIT 1) then ... end if;
(_id - какойто входной аргумент, а `id` - поле таблицы, первичный ключ).

Но вот возник вопрос - насколько "умен" мускль: в случае нахождения нужного элемента по ПК или уникальному полю прекратит ли он дальнейший поиск?
т.е. будет ли с точки зрения скорости работы равны следующие запросы:

SELECT 1 FROM `some_table` t WHERE t.`id` = _id LIMIT 1;
SELECT 1 FROM `some_table` t WHERE t.`id` = _id;


Жадный коллекционер CPU тиков smile

Неактивен

 

#2 24.04.2007 17:03:38

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6718

Re: limit'ы для PK и U-индексов

В данном конкретном случае LIMIT не играет никакой роли. MySQL
понимает, что имеет дело с WHERE-указанием по уникальному ключу,
а значит - строчка получится всегда максимум одна. Такие запросы
проходят всегда с использованием индекса.

Если же индекс не уникальный - то LIMIT может значительно ускорить
обработку запроса. Без LIMIT оптимизатор будет оценивать cardinality
индекса, количество строк и другие параметры таблицы. Возможен случай,
когда индекс вообще не будет использоваться. В случае с LIMIT, он
остановится на одной строке, которую найдет опять же по индексу.

Неактивен

 

#3 24.04.2007 17:08:05

anky
Участник
Откуда: Киев
Зарегистрирован: 17.04.2007
Сообщений: 12

Re: limit'ы для PK и U-индексов

Т.е. получается что в таком случая я лишь усугубляю работу БД лишними критериями smile
спасибо!

да, кстате сразу хотел спросить, есть ли здравый смысл в использовании других конструкций кроме
if exists() then..
в телах функций, где добавление INSERT'ом дублирующих уникальных значение вызовет критическую ошибку 1062 (вроде roll), которая очень нехорошо будет смотреться в PHP коде...

Отредактированно anky (24.04.2007 17:11:17)


Жадный коллекционер CPU тиков smile

Неактивен

 

#4 24.04.2007 17:41:25

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6718

Re: limit'ы для PK и U-индексов

Все зависит от Вашего стиля написания программы. IF EXISTS() требует
наличия транзакций, т.к. Вы не можете быть уверены, что строчка не появится
(или не исчезнет) вдруг вследствие работы другого потока.

Для MyISAM Вы можете пользоваться INSERT IGNORE или REPLACE, которые,
соответственно, не изменяют строчку (которая совпадает по уникальным
ключам) или заменяют ее на новые данные. При этом реально произведенное
действие можно оценить по количеству измененных строк: в случае обычного
добавления будет одна строка, в случае срабатывания IGNORE - будет изменено
ноль строк, в случае замены REPLACE - две (удаление + добавление новой).

Существует еще возможность обновлять строчку при совпадении уникальных
индексов: ON DUPLICATE KEY UPDATE. Обо всем этом, разумеется, можно
прочитать в документации.

Неактивен

 

#5 25.04.2007 18:47:04

anky
Участник
Откуда: Киев
Зарегистрирован: 17.04.2007
Сообщений: 12

Re: limit'ы для PK и U-индексов

дело в том что мне надо отслеживать результат - т.е. была ли успешно добавлена запись или нет.
конечно, как вариант - использовать в РНР mysql_affected_rows вместе с INSERT IGNORE...
стоит ли тогда менять?

вот кусок функции, в РНР уже идет обработка результата и вывод сообщений ,в случае ошибок (связанных с дублированием)

Код:

CREATE FUNCTION `p_de_users`(_login varchar(20)) RETURNS tinyint(1)
begin
if  exists ( SELECT 1 FROM `v_id_users` t WHERE t.`login` = _login) then
    UPDATE `users` SET `users`.`deleted` = 1 where `users`.`login` = _login;
    return 0;
end if;
return -1;
end

аналогично INSERT сейчас работает

Отредактированно anky (25.04.2007 18:58:40)


Жадный коллекционер CPU тиков smile

Неактивен

 

#6 26.04.2007 01:40:17

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6718

Re: limit'ы для PK и U-индексов

Для UPDATE никаких подковырок я тут не вижу, если запись есть,
то ее могут пометить удаленной два потока одновременно. В случае с
INSERT, у Вас могут быть проблемы с уникальными полями. Представьте
себе ситуацию, когда два потока пытаются это сделать одновременно.

Первый поток делает проверку на наличие строки: строки нету. Далее
процессор переключается на второй поток, который делает такую же
проверку и вставляет строчку. Процессор переключается на первый поток,
который пытается вставить строчку и получает ошибку. Спасти от этого
сможет только поддержка транзакций, которой в MyISAM нету. Поэтому,
если Вы используете таблицы MyISAM, я Вам рекомендую переписать
INSERT-версию процедуры через INSERT IGNORE. Для определения
успешности завершения операции внутри процедуры, можно использовать
ROW_COUNT().

С другой стороны, на не загруженном сервере вероятность одновременной
вставки, разумеется, очень мала.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson