Программирование >>  Проектирование баз данных 

1 ... 65 66 67 [ 68 ] 69 70 71 ... 184


Однако в действительности без предложения ORDER BY это делать опасно. Так как наша уверенность в том, что нужной окажется первая возврашенная строка, основывается на наличии определенных индексов и на том, что оптимизатор запросов выберет эти индексы. Более надежным является выполнение такого соединения внутри приложения (либо в PL/SQL, либо с помощью какого-нибудь ЗОЕ-средства со встроенным SQL), в результате чего для каждого из двух запросов будет выбираться только одна строка.

Что делать с проверкой по двум диапазонам?

Представим, что у нас есть запись о товаре, содержащая дату первого выпуска товара в продажу и (для товаров, снятых с продажи) дату снятия с продажи. Аналитики хотят знать, какие из этих товаров поступили в продажу в период с 1 февраля 1970 года по 31 марта 1972 года, а какие сняты с продажи в период с 1 января 1980 года по 15 февраля 1981 года. Нет проблем , - скажете вы и напишете следующий простой SQL-запрос:

SELECT р.product code

, р.date realeased , р.date.dropped FROM products p

WHERE p.date released BETWEEN Ol-FEB-70 AND 31-MAR-T2

AND p.date dropped BETWEEN Ol-JAN-80 AND 15-FEB-81

К сожалению, вы ошибаетесь, если полагаете, что проблема решена. Дело в том, что для больших объемов данных приемлемого метода оптимизации такого запроса в Oracle нет.

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

Решение состоит в хранении производного поля для каждого измерения. Это поле содержит значение, которое можно искать, выполняя сравнение на равенство. В нашем примере мы могли бы использовать календарный месяц и ввести это значение с помощью триггера. Затем необходимо построить индекс (MONTH RELEASED, MONTH DROPPED). Когда мы строим запрос, мы передаем ему номер (:query) и вставляем в управляющую таблицу (QUERY DRIVER) все пары месяцев, которые нас могли бы заинтересовать. В данном примере 42 такие пары. Затем мы выполняем запрос, подобный следующему:

SELECT p.product code

, p.date realeased , p.date.dropped FROM query! = :query products p



WHERE q.query* = :query

AND p.nionth released = p .nionth released

AND p.nionth dropped = p .month dropped

AND p.date released BETWEEN Ol-FEB-70 AND 31-MAR-72 AND p.date dropped BETWEEN Ol-JAN-80 AND 15-FEB-81

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

Нас часто спрашивают, почему мы пользуемся в этом примере управляющей таблицей (управляющая таблица влечет за собой и дополнительные расходы, и существенные осложнения) вместо того, чтобы просто генерировать при помощи оператора IN значения для поиска в индексе. Эта форма показана в следующем операторе SELECT, но здесь есть проблема: многие версии оптимизатора запросов содержат эвристический механизм, который обрабатывает длинные списки аргументов IN путем полного сканирования таблицы. Используйте эту форму только в случае, если вы уверены, что используемый вами оптимизатор всегда будет инициировать поиск в индексе. Если же вас устраивает полное сканирование таблицы, то этот запрос будет работать просто прекрасно (либо при отсутствии индексов, либо при использовании подсказки оптимизатора /* +FULL */).

/* Базовый месяц - январь 1970 г., значение 1 */

SELECT p.product code

, р.date realeased , р.date.dropped FROM products p WHERE q.query* = :query

AND (p.month released, p.month dropped) IN

((1, 121), (1, 122), (1, 123), ... (3, 134)) AND p.date released BETWEEN Ol-FEB-70 AND 31-MAR-72 AND p.date dropped BETWEEN Ol-JAN-80 AND 15-FEB-81;

Проблема при сравнении по двум диапазонам заключается в том, что при помощи естественных данных невозможно добраться до уровня, на котором можно использовать либо равенство, либо проверку диапазона (т.е. где нужные ключевые значения в индексе будут расположены рядом). Если бы мы не изобрели столбцы MONTH, то для поиска необходимых товаров нам пришлось бы выполнить одно из следующих действий:

проверить столбец DATE DROPPED для каждого товара, вошедшего в диапазон DATE RELEASED;

проверить столбец DATE RELEASED для каждого товара, вошедшего в диапазон DATE DROPPED.



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

Временные данные: резюме

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

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

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

Если действительная конечная дата не известна, рекомендуется заносить в столбец большое значение, например, 31-DEC-4712.

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

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

Бизнес-правила, запрещающие перекрытия и разрывы во временном ряде, можно реализовать при помощи триггеров.

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

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

Для решения проблемы проверки по двум диапазонам потребуется прибегнуть к нетрадиционным решениям. Если эти решения слишком дороги в плане реализации и производительности, то придется использовать OLAP-процессор или многомерный процессор.

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

л , .i



1 ... 65 66 67 [ 68 ] 69 70 71 ... 184

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика