получить только первый ряд из оракула - это быстрее? - PullRequest
1 голос
/ 13 июня 2010

Моя главная цель в этом вопросе - оптимизация и ускорение работы.

После большой обработки в сохраненном процессе я наконец возвращаю счет, как показано ниже:

          OPEN cv_1 FOR
             SELECT COUNT(*) num_of_members
               FROM HOUSEHOLD_MEMBER a,
                    HOUSEHOLD b
                WHERE RTRIM(LTRIM(a.mbr_last_name)) LIKE v_MBR_LAST_NAME || '%'
                        AND a.number = '01'
                        AND a.code = v_CODE
                        AND a.ssn_head = v_SSN_HEAD
                        AND TO_CHAR( a.mbr_dob, 'MM/DD/YYYY') = v_DOB;

Но в моем коде, который вызывает SP, не нужен фактический счетчик. Просто волнует, что количество больше 1.

Вопрос:

  1. Как я могу изменить это, чтобы возвращать только 1 или 0. 1, когда count> 0 и 0, когда count> 1.
  2. Будет ли это быстрее, чем возвращать весь счет?

Ответы [ 5 ]

2 голосов
/ 14 июня 2010

Если вам не нужны фактические данные и вы хотите знать, есть ли хотя бы 1, вы можете использовать ROWNUM для его оптимизации:

OPEN cv_1 FOR
    SELECT 1 has_at_least_one_member
    FROM HOUSEHOLD_MEMBER a,
         HOUSEHOLD b
    WHERE RTRIM(LTRIM(a.mbr_last_name)) LIKE v_MBR_LAST_NAME || '%'
    AND a.number = '01'
    AND a.code = v_CODE
    AND a.ssn_head = v_SSN_HEAD
    AND TO_CHAR( a.mbr_dob, 'MM/DD/YYYY') = v_DOB
    AND ROWNUM = 1;

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

На несвязанной ноте я предлагаю (согласно примечанию Даффимо) удалить TO_CHAR вокруг a.mbr_dob и добавить TO_DATE вокруг v_DOB.Таким образом, если в a.mbr_dob есть индекс, у Oracle есть возможность использовать его.

1 голос
/ 14 июня 2010

Мой опыт показывает, что часто быстрее извлечь одну строку из курсора, чем извлечь COUNT (). Это полезно, если вам нужно знать, что совпадающие данные существуют, но не беспокоиться о количестве строк. В этом случае код можно переписать как

DECLARE
  bRow_found  BOOLEAN := FALSE;
BEGIN
  FOR aRow IN (SELECT a.mbr_last_name
                 FROM HOUSEHOLD_MEMBER a, 
                      HOUSEHOLD b 
                 WHERE RTRIM(LTRIM(a.mbr_last_name)) LIKE v_MBR_LAST_NAME || '%' 
                       AND a.number = '01' 
                       AND a.code = v_CODE 
                       AND a.ssn_head = v_SSN_HEAD 
                       AND TO_CHAR( a.mbr_dob, 'MM/DD/YYYY') = v_DOB)
  LOOP
    bRow_found := TRUE;
    EXIT;
  END LOOP;
END;

Делись и наслаждайся.

1 голос
/ 13 июня 2010

Я бы не подумал, что введение фильтра на счетчике (*) поможет повысить производительность, но, как уже было сказано, это можно сделать с помощью предложения HAVING.

Возможно, самым большим узким местом у вас будут ваши объединения.

WHERE RTRIM(LTRIM(a.mbr_last_name)) LIKE v_MBR_LAST_NAME || '%'

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

AND TO_CHAR( a.mbr_dob, 'MM/DD/YYYY') = v_DOB;

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

Лучший способ оптимизировать это - получить план объяснения:

EXPLAIN PLAN FOR
  ...
0 голосов
/ 13 июня 2010

Что значит «первый»? Без предложения WHERE вы не знаете, в каком порядке хранятся строки в реляционной базе данных.

Есть ли у вас данные, свидетельствующие о проблемах с производительностью, или вы преждевременно оптимизируете?

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

Начните здесь:

AND TO_CHAR( a.mbr_dob, 'MM/DD/YYYY') = v_DOB;

Я думаю, что если вы объясните это, вы обнаружите, что TO_CHAR заставит Oracle использовать TABLE SCAN. Любой указатель на дату рождения в этом случае бесполезен.

Это подсказывает мне, что вы смоделировали столбец даты рождения в виде строки / VARCHAR. С какой стати ты это сделал? Используйте столбец DATE и передайте правильную переменную даты. Ваша производительность улучшится, и у вас будет фактическое количество домашних хозяйств. Это кажется полезным для меня.

0 голосов
/ 13 июня 2010

Вы можете использовать HAVING, чтобы проверить, что COUNT больше 1.

CURSOR c_example IS
SELECT COUNT(*)
...
HAVING COUNT(*) > 1;
l_dummy PLS_INTEGER;


OPEN c_example;
FETCH c_example INTO l_dummy;
IF c_example%NOTFOUND THEN
  CLOSE c_example;
  RETURN FALSE
ELSE
  CLOSE c_example;
  RETURN TRUE
END IF;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...