Когда «IN», а когда нет? - PullRequest
       19

Когда «IN», а когда нет?

1 голос
/ 20 июля 2009

Давайте предположим, что вы пишете заявку для сети розничных магазинов.Таким образом, вы должны разработать свою объектную модель так, чтобы вы определяли «Store» как основной бизнес-объект и множество вспомогательных объектов.Допустим, «Магазин» выглядит следующим образом:

class Store implements Validatable{
int storeNo;
int storeName;
... etc.... 
}

Итак, ваш клиент говорит вам, что вам нужно импортировать расписание магазина из таблицы Excel в приложение, и вам нужно будет запустить серию проверок ».Эм.Например, «StoreIsInSameCountry»; «StoreIsValid» ... и т. Д. Итак, вы должны разработать интерфейс правил для проверки всех бизнес-условий.Примерно так:

interface Rule T extends Validatable> {
public Error check(T value) throws Exception;
}

Теперь возникает вопрос.Я загружаю 2000 магазинов из этого листа Excel.Таким образом, я бы закончил выполнение каждого правила, определенного для магазина, много раз.Если бы у меня было 4 правила = 8000 запросов к базе данных, то есть 16000 обращений к пулу соединений.Для простой проверки, где мне просто нужно проверить, существует ли хранилище, запрос будет выглядеть так:

 SELECT STORE_ATTRIB1, STORE_ATTRIB2... from STORE where STORE_ID = ?

Таким образом, я получу свой объект Store.Когда я ничего не получаю из базы данных, тогда этот магазин не существует.Итак, для такой простой проверки мне пришлось бы обращаться к базе данных 2000 раз для 2000 магазинов.

В качестве альтернативы, я мог бы просто сделать:

SELECT STORE_ATTRIB1, STORE_ATTRIB2... from STORE where STORE_ID in (1,2,3..... ) 

Этот запрос на самом деле будет возвращаться намного быстрее, чем выполнение запроса выше 2000 раз.Тем не менее, не очень хорошо с дизайном, что правило может быть запущено только для одного магазина.

Я знаю, что использование IN не является рекомендуемой методологией.Итак, что вы думаете, я должен делать?Должен ли я пойти дальше и использовать IN здесь, потому что это дает лучшую производительность в этом сценарии?Или я должен изменить свой дизайн?

Что бы вы сделали, если бы вы были на моем месте, и какова лучшая практика?

Ответы [ 3 ]

2 голосов
/ 20 июля 2009

Таким образом я получу свой объект «Store» из базы данных. Когда я ничего не получаю из базы данных, тогда этот магазин не существует. Итак, для такой простой проверки мне нужно было бы просмотреть базу данных 2000 раз для 2000 магазинов.

Это то, что вы не должны делать.

Создайте временную таблицу, заполните таблицу своими значениями и JOIN эту таблицу, например:

SELECT  STORE_ATTRIB1, STORE_ATTRIB2...
FROM    temptable tt
JOIN    STORE s
ON      s.STORE_ID = t.id

или это:

SELECT  STORE_ATTRIB1, STORE_ATTRIB2...
FROM    STORE s
WHERE   s.STORE_ID IN
        (
        SELECT  id
        FROM    temptable tt
        )

Я знаю, что использование IN не является рекомендуемой методологией. Итак, что вы думаете, я должен делать? Должен ли я пойти дальше и использовать IN здесь, потому что это дает лучшую производительность в этом сценарии? Или я должен изменить свой дизайн?

IN отфильтровывает дубликаты.

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

IN ни в коем случае не является «не рекомендуемой методологией».

На самом деле, было время, когда некоторые базы данных не поддерживали IN запросов эффективно, поэтому народная мудрость все еще советует не использовать его.

Но если ваш store_id проиндексирован правильно (и, скорее всего, если PRIMARY KEY выглядит так), то все современные версии основных баз данных (то есть Oracle, SQL Server, MySQL и PostgreSQL) будут использовать эффективный план для выполнения этого запроса.

См. Эту статью в моем блоге для деталей производительности в SQL Server:

Обратите внимание, что в правильно спроектированной базе данных правила валидации также основаны на наборах.

I. е. Вы реализуете свои правила проверки как запросы к temptable.

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

1 голос
/ 20 июля 2009
SELECT store_id FROM store WHERE store_active = 1

или даже

SELECT store_id FROM store

скажет вам все активные магазины в одном запросе. Теперь вы можете проводить другие тесты в магазинах, о которых вы знаете, что они существуют, и вы сохранили 1 999 посещений в базе данных.

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

0 голосов
/ 20 июля 2009

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

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

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