Rambler's Top100

(c)2009-2017 openinfotech.ru

СУБД HyTech

Документация
Поиски

Поисковые операции

Типы поисковых операций

Все поисковые операции можно условно разделить на несколько классов:

  • Поиски записей.
  • Поиски значений полей.
  • Межтабличные поиски.
  • Операции над группами.
  • Прочие поиски.

К первому классу относятся поиски, результатом которых является некоторое подмножество записей в искомой таблице (может быть все). Такие поиски также удобно разделить на три группы:

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

Атомарным поиском назовем такой поиск записей, когда значения одного из элементов записи (поля, группы или подстроки) удовлетворяет определенному условию. Например, "год_рождения" равен 1960. Здесь будут найдены записи, в которых значение поля "год_рождения" равно 1960.

Естественно, что необходимо иметь возможность организации логических связок результатов атомарных поисков. К таким операциям можно отнести - отрицание, логическое "И", логическое "ИЛИ" и исключающее "ИЛИ".

К третьей группе относятся операции преобразования списков значений поля (группы, подстроки) в список записей. Например, можно получить список записей, у которых поле "год_рождения" принимает одно из следующих значений { 1950, 1960, ..., 1990 }. Очевидно, что для выполнения этой операции необходимо иметь сформированный список значений какого-либо поля (см.ниже).

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

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

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

В третий класс операций выделены операции межтабличного поиска. Эти операции позволяют выполнить "слияние" нескольких таблиц для порождения "виртуальных" результирующих таблиц. Виртуальность таблиц-результатов заключается в том, что они не существуют на момент поиска (впрочем, СУБД имеет средства для преобразования "виртуальных" таблиц в реальные).

Операции этого класса позволяют реализовывать межтабличные отношения "один к одному", "один ко многим" и "многие ко многим". Например, пусть в таблице AREA содержится описание территорий ("код_области", "область"), в таблице PEOPLE - описание заболевших людей ("паспорт", "фамилия", "код_области" и т.п.). Тогда для формирования таблицы WHERE ("фамилия", "область" ) нужно выполнить операцию "слияния" таблиц AREA и PEOPLE через общее поле "код_области", в результате которой будет получена новая, до этого не существовавшая, таблица.

Операции четвертого класса позволяют вычислить некоторые библиотечные функционалы (MAX, MIN, SUM, AVERAGE, COUNT и т.п.), разбив подмножество записей на некоторые группы (сгруппировав их по

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

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

Концепция поиска. "Фотография" состояния БД

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

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

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

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

Снимок можно получить и не выполняя поиска при помощи функции htMakePhoto().

Для "освежения" снимка, т.е. коррекции результатов поиска в соответствии с новым состоянием БД, предназначена функция htTouchResults().

Снимок БД не является подмножеством записей таблицы, а содержит некоторую информацию, связанную в ее состоянием в текущий момент времени. Поэтому "снимок" не может быть уточнен или сужен, так как это делается с подмножеством записей.

Операция обновления таблицы (htUpdateTable) дезавуирует все "снимки", выполненные ранее.

Блок Доступа к Сервису (БДС)

БДС представляет собой структуру вида:

typedef struct tagBCB {
	int 		nRetCode; 	/* Код завершения операции */
	long	 	gFoundCnt; 	/* Число элементов в результате */
	const char 	mPrivate[94]; 	/* Системные переменные */
} SAB;

БДС выделяется в пользовательской программе и используется для "общения" с СУБД. Все поисковые операции имеют в качестве параметра один или несколько адресов БДС. После выполнения операции СУБД заносит в системные поля БДС результаты поиска и параметры, характеризующие состояние таблицы (ее "снимок"). Кроме того в БДС заносится число найденных элементов (записей, значений ключа и т.п.) и код завершения операции.

Для определения типа результата, хранимого в БДС можно воспользоваться функцией htResultsType().

Заполненный БДС может использоваться далее как операнд других поисковых функций или для доступа к найденным результатам.

Выделение БДС в программе может выполняться:

  • статически (как локальные или глобальные переменные);
  • динамически (при помощи функций malloc, alloca и т.п.).

Предварительная очистка полей БДС перед его использованием не требуется. Единственным исключением является функция htClearResults(), которая удаляет результаты поиска, содержащиеся в БДС. Естественно, что БДС должен содержать "осмысленные" результаты или быть "пустым" (заполнен двоичными нулями).

Удаление результатов БДС нужно выполнять сразу, как только результаты поиска становятся "ненужными". При этом освобождаются ресурсы, занимаемые результатами (область памяти или файлы). Если этого не делать своевременно, снижается не только производительность СУБД, но и объем ресурсов, доступных прикладной программе.

При повторном использовании "заполненного", но не очищенного (через htClearResults) БДС, хранимые в нем результаты будут утеряны (но не удалены). Это приведет к нежелательным последствиям (уменьшение количества доступной памяти или дискового пространства) или даже невозможности дальнейшей работы.

Пример.

Выделение БДС статически и динамически.

SAB global; /* Глобальная переменная */
void func()
{	SAB 	local; /* Локальная переменная */
	LPSAB 	ptrSab; /* Указатель на БДС */
	LPSAB 	ptrZero; /* Указатель на БДС */

	ptrSab = malloc( sizeof(SAB) );
	ptrZero = calloc( 1, sizeof(SAB) );
}

Пример.

Определение типа результата, хранимого в БДС.

void TellSabType( LPSAB fpSAB )
{
	switch( htResultsType( fpSAB ) )
	{ case RES_RECORD:
		/* БДС содержит список записей */
		break;
	 case RES_VALUE:
		/* БДС содержит список значений ключа */
		break;
	 case RES_HISTO:
		/* БДС содержит гистограмму */
		break;
	 case RES_JOIN:
		/* БДС содержит результат слияния таблиц */
		break;
	 case RES_SORTED:
		/* БДС содержит отсортированный список записей */
		break;
	 case RES_GROUP:
		/* БДС содержит результаты операции GROUP BY */
		break;
	 case RES_NPROC:
		/* БДС не обработан, или результаты удалены */
		break;
	 case RES_SORTJOIN:
		/* БДС содержит сортированный результат слияния таблиц */
	}
}

Пример.

Удаление результатов поиска после из использования.

long gRecNo = 100L;
SAB sSearch;
THANDLE hTable;
 . . .
htSearch( NULL, &sSearch, hTable, 0, GREAT, &gRecNo, NULL );
 . . .
htClearResults( &sSearch ); /* Теперь БДС можно использовать повторно */
 . . .
htSearch( NULL, &sSearch, hTable, 0, LESS, &gRecNo, NULL );