Есть ли способ оптимизировать запрос, приведенный ниже? - PullRequest
0 голосов
/ 17 декабря 2008

У меня есть следующий запрос, и мне нужен запрос для извлечения данных из SomeTable на основе критериев фильтра, присутствующих в Someothertable. Если в SomeOtherTable Query ничего нет, я должен вернуть все данные, имеющиеся в SomeTable

SQL SERVER 2005

SomeOtherTable не имеет индексов или ограничений. Все поля имеют тип char (50)

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

В связи с некоторыми требованиями Клиента, мы должны хранить все данные предложения Where в SomeOtherTable. в зависимости от subid данные будут объединены с одним из столбцов в SomeTable.

Например, запрос может быть

SELECT
    *
FROM
    SomeTable
WHERE
    1=1 
AND
(
SomeTable.ID in (SELECT DISTINCT ID FROM SomeOtherTable  WHERE Name = 'ABC' and subid = 'EF')
OR
0=(SELECT Count(1) FROM SomeOtherTable WHERE spName = 'ABC' and subid = 'EF')
)

AND 
    (
    SomeTable.date =(SELECT date FROM SomeOtherTable  WHERE Name = 'ABC' and subid = 'Date')
    OR
    0=(SELECT Count(1) FROM SomeOtherTable WHERE spName = 'ABC' and subid = 'Date')
    )

EDIT ----------------------------------------------

Думаю, мне придется подробно объяснить мою проблему:

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

В приложении ASP.net мы создали мастера, которые используются для передачи параметров в отчеты. Эти параметры не напрямую используются отчетом Crystal, но используются запросом, встроенным в отчет Crystal, или процедурой Stored, используемой в Хрустальный отчет.

Это достигается с помощью таблицы (SomeOtherTable), в которой хранятся данные параметров, пока выполняется отчет, после которого данные удаляются, поэтому мы можем предположить, что SomeOtherTable имеет максимум 2-3 строки в любой заданный момент времени.

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

Так что я не думаю, что будет полезно создавать индексы и т. Д. (Может быть, я ошибаюсь).

Ответы [ 9 ]

3 голосов
/ 19 декабря 2008

SomeOtherTable не имеет каких-либо индексы или любое ограничение всех полей Чарс (50)

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

  • Вам нужен правильный первичный или другой кандидатный ключ, обозначенный на всех ваших столах. То есть вам нужен по крайней мере ОДИН уникальный индекс в таблице. Вы можете сделать это, назначив одно или несколько полей в качестве PK, или вы можете добавить УНИКАЛЬНОЕ ограничение или индекс.

  • Вам необходимо правильно определить поля. Поле хранит целые числа? Итак, поле INT может быть лучшей ставкой, чем CHAR (50).

Вы не можете "оптимизировать" запрос, основанный на неверной схеме.

2 голосов
/ 17 декабря 2008

Попробуйте:

SELECT
    *
FROM
    SomeTable
LEFT JOIN SomeOtherTable ON SomeTable.ID=SomeOtherTable.ID AND Name = 'ABC'
WHERE
    1=1 
AND
(
SomeOtherTable.ID IS NOT NULL
OR
0=(SELECT Count(1) FROM SomeOtherTable WHERE spName = 'ABC')
)
1 голос
/ 17 декабря 2008

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

если EXISTS (выберите spName из SomeOtherTable, где spName = 'ABC') начать ВЫБРАТЬ * ОТ SomeTable ГДЕ SomeTable.ID в (ВЫБЕРИТЕ ID ИЗ SomeOtherTable, где Name = 'ABC') конец еще начать ВЫБРАТЬ * ОТ SomeTable конец

1 голос
/ 17 декабря 2008

Следующее может ускорить вас

SELECT * 
FROM SomeTable 
WHERE
   SomeTable.ID in 
        (SELECT DISTINCT ID FROM SomeOtherTable Where Name = 'ABC')
UNION
SELECT * 
FROM SomeTable 
Where 
   NOT EXISTS (Select spName From SomeOtherTable Where spName = 'ABC')

UNION эффективно разделит это на два более простых запроса, которые можно оптимизировать отдельно (очень сильно зависит от СУБД, размера таблицы и т. Д., Действительно ли это улучшит производительность - но всегда стоит попробовать).

Ключевое слово «EXISTS» более эффективно, чем «SELECT COUNT (1)», так как оно вернет true, как только встретится первая строка.

1 голос
/ 17 декабря 2008

также ставьте 'with (nolock)' после каждого имени таблицы для улучшения производительности

0 голосов
/ 19 декабря 2008

Мне кажется, что в вашем запросе нет необходимости "1 = 1 AND". 1 = 1 всегда будет оцениваться как истинное, оставляя программное обеспечение для оценки следующей части ... почему бы просто не пропустить 1 = 1 и оценить сочную часть?

0 голосов
/ 19 декабря 2008

Я собираюсь придерживаться моего оригинального запроса.

0 голосов
/ 17 декабря 2008

измените все ваши операторы select в части where на внутренние jons. Условия OR должны быть объединены. также убедитесь, что с индексированием все в порядке.

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

0 голосов
/ 17 декабря 2008

Aloha

Попробуйте

select t.* from SomeTable t
    left outer join SomeOtherTable o
        on t.id = o.id
where (not exists (select id from SomeOtherTable where spname = 'adbc')
OR spname = 'adbc')

-Edoode

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