Использование хранимой процедуры в качестве «динамического» представления? - PullRequest
1 голос
/ 22 апреля 2009

Я хочу создать «представление», чтобы исключить тот же трехстрочный подзапрос из примерно 90 запросов в приложении, над которым я работаю.

Проблема в том, что подзапрос содержит условие на основе переменной.

SELECT * FROM items WHERE id NOT IN (
  SELECT item_id FROM excluded_items WHERE user_id = 123
);

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

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

SELECT * FROM user_items(123);

Теперь у меня есть единственное место, чтобы обновить исключение этого элемента и любые другие условия, однако я не уверен, как повлияет индексирование, если я хочу объединить результаты этого SP с другими таблицами?

Так это хорошая / плохая практика? Есть ли другой способ сделать это, или я должен просто смириться с этим и продолжать реплицировать этот подзапрос?

Ответы [ 4 ]

3 голосов
/ 22 апреля 2009

Как обычно Ваш пробег может варьироваться . Если вы беспокоитесь о том, что это хорошая практика с точки зрения синтаксиса кода, я не думаю, что это имеет значение. Это довольно обычная вещь - использовать хранимую процедуру для возврата наборов записей, и если это экономит ваше время на разработку, то почему бы не сделать это? Однако, если вы определили, что стоимость времени выполнения вашего запроса подвергается такому негативному влиянию, что ваш бизнес стоит больше, чем ваша производительность как программиста, тогда ни в коем случае не используйте хранимые процедуры.

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

Чтобы определить, как именно изменение влияет на производительность, выполните несколько тестовых запросов, используя:

EXPLAIN ANALYZE SELECT * FROM items WHERE id NOT IN (
  SELECT item_id FROM excluded_items WHERE user_id = 123
);

, а затем

EXPLAIN ANALYZE SELECT * FROM user_items(123);

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

2 голосов
/ 08 июня 2009

Вы пробовали что-то вроде

create view user_items as (
  select i.*, u.id as user_id
    from (items i cross join users u)
      left join excluded_items e
      on (i.id = e.item_id
        and u.id = e.user_id)
    where e.item_id is null
);

уже? Я проверил это с PostgreSQL 8.3, который может вывести условие user_id в перекрестное соединение, если вы используете представление в простых запросах, таких как

select *
  from user_items ui
  where user_id = 1;

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

1 голос
/ 22 апреля 2009

Я думаю, что решение хранимых процедур более СУХОЕ и действительно улучшает читабельность. Хотя я, конечно, предпочитаю использовать представления, где это возможно (особенно с мощными правилами PostgreSQL), я просто не могу придумать более хороший способ выразить это.

0 голосов
/ 22 апреля 2009

Наличие одного и того же SQL в 90 местах может быть решено и на стороне клиента. Например, создайте функцию, которая создает строку SQL:

public string SqlItemsForUser(int iUserId) {
    return "SELECT * FROM items WHERE id NOT IN ( " +
        "SELECT item_id FROM excluded_items WHERE user_id = " +
        Convert.ToString(iUserId) + ");";
}

Вы можете вызывать эту функцию в 90 местах, поэтому, если вам нужно изменить подзапрос, вам нужно изменить его только в одном месте.

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