SWD Software Ltd. - официальный дистрибьютор QNX на территории России и стран бывшего СССР Операционная система реального времени QNX
Инструменты для создания надёжных встраиваемых систем и
интеллектуальных устройств любой сложности
QNX Software Systems - разработчик встраиваемой операционной системы QNX
  Стандартная версия

Индекс для поиска текста в базе данных Empress Ultra Embedded 10.20 обеспечивает быстрый способ извлечения текстовых данных – Часть 1

Введение

В системе управления базами данных (СУБД) Empress Ultra Embedded 10.20 для разработчиков встраиваемых приложений предлагается ряд дополнительных функций. Одной из таких функций является возможность использования индекса для поиска текста (Text Search Index).

Индекс для поиска текста в СУБД Empress

Возможность применения в СУБД Empress Ultra Embedded V10.20 индекса для поиска текста предоставляет разработчикам приложений мощное средство, позволяющее реализовать эффективный поиск по записям базы данных, используя для этого ключевые слова/лексемы/фразы. Наиболее типичным примером реализации этой возможности является связывание таких ключевых слов с конкретными символьными/текстовыми атрибутами в таблице базы данных.

Функции индексного поиска разработаны в виде дополнительного набора С-вызовов, которые используются в тесной связи с процедурами C/C++ API уровня ядра СУБД Empress (Empress C/C++ Kernel Level API – mr Routines). Индексный поиск поддерживается и реализуется пользователем – он не входит в состав вызовов через механизмы СУБД Empress.

Для реализации индексного поиска текста со стороны приложения необходимо включить в состав СУБД Empress список (массив) лексем/ключевых слов/фраз.

Давайте рассмотрим пример, когда в СУБД Empress в атрибуте данных типа TEXT сохраняются заголовки песен. Для известной песни Битлз “I Want To Hold Your Hand” список лексем/ключевых слов/фраз может выглядеть таким образом:

Want
Hold
Hand
I
Hold Your
Your Hand
Hold Your Hand

В этом примере список состоит из семи лексем. Лексема может представлять собой единственное слово или может включать несколько слов. Включаемые слова могут и не присутствовать изначально в исходном заголовке песни. Например, для заголовка песни “Old Macdonald” вполне возможно использовать лексемы Mc или Mac.

Будучи один раз созданным, индекс для поиска текста в СУБД Empress с введенными лексемами/ключевыми словами представляет собой достаточно мощную функцию поиска.

При наличии сотен тысяч заголовков поиск заголовка песни со словом Hold может привести к выдаче такого множества названий:

You Really Got A Hold on Me (Beatles)
If We Hold On (Diana Ross)
I Want To Hold Your Hand (Beatles)
Hold Me Back (Ac/Dc)
Hold Me, Thrill Me, Kill Me (U2)

Поиск информации с использованием индекса

Приводимый ниже пример представляет собой программный код (файл select_text.c), использующий процедуры C/C++ API уровня ядра СУБД Empress, который демонстрирует, как происходит поиск записей в таблице songs с помощью индекса, составленного для той же самой таблицы. В программе С-вызовы API индекса для поиска выделены жирным шрифтом. В программе производится поиск всех записей в таблице songs, в которых содержится нужная лексема. При переводе на язык SQL-запроса пример выглядел бы так:

SELECT id, title FROM songs WHERE title HAS “Hold

#include     
#include     
  
#ifdef  WINCE 
global_shared_func      msbool      mssio_printf (char* format, ...); 
#define     swprintf    _snwprintf 
#define     printf            mssio_printf 
#endif 
   
#define     DATABASE   L"karaokedb" 
   
int   msmain (int argc, 
            char* argv[]) 
{ 
	void*           songs_tabdesc; 
	void*           id_attrdesc; 
	void*           title_attrdesc; 
	void*           songs_recdesc; 
	void*           qual; 
	void*           retrieve_desc; 
	wchar_t*        id_value; 
	wchar_t*        title_value; 
	void*           index_handle; 
	long*           record_list; 
	char            buf[1024]; 


	songs_tabdesc = mropen (DATABASE, L"songs", 'r'); 

	songs_recdesc = mrmkrec (songs_tabdesc); 
	id_attrdesc = mrngeta (songs_tabdesc, L"id"); 
	title_attrdesc = mrngeta (songs_tabdesc, L"title"); 
	
	index_handle= mstsi_open (songs_tabdesc , title_attrdesc, 'r'); 

	id_value = mrspv (id_attrdesc); 
	title_value = mrspv (title_attrdesc); 
	   
	printf ("Songs that contain token Hold

"); 
	printf (buf, "%-12s %-22s
", "Id", "Title"); 

	record_list = mstsi_get (index_handle, L"Hold", 0); 
	if (record_list == 0) 
	{ 
		printf ("No songs with token Hold
"); 
		return 0; 
	}   
	qual = mrqlst (songs_tabdesc, record_list); 

	retrieve_desc = mrgetbegin (qual, songs_recdesc, (void*) 0); 

	while (mrget (retrieve_desc)) 
	{ 
	   mrcopyv (songs_recdesc, id_attrdesc, id_value); 
	   mrcopyv (songs_recdesc, title_attrdesc, title_value); 
	   sprintf (buf, "%-12ls %-22ls
", id_value, title_value); 
	   printf ("%s", buf); 
	} 
	mrgetend (retrieve_desc); 

	mrfree (id_value); 
	mrfree (title_value); 
	mrfrrec (songs_recdesc); 

	mstsi_close (index_handle);   
	
	mrclose (songs_tabdesc); 

	printf ("select1_text is done
"); 
	return 0; 
}

Эффективность выполнения поиска

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

SELECT id, title FROM songs WHERE title LIKE “%Hold%

или такого

SELECT id, title FROM songs WHERE title SMATCH “*Hold*

В другом примере поиск ключевого слова "Embedded" осуществлялся на множестве всех заголовков данных из Википедии, хранящихся в СУБД Empress. В таблице pages содержалось 7649051 заголовков (titles) и связанной с ними информации, например, идентификаторов (id) и имен авторов (author).

При использовании индекса для поиска текста процедура поиска заняла 0,077 сек, и её результатом стало множество из 131 заголовка.

Для сравнения был сформирован аналогичный SQL-запрос для поиска заголовка title по атрибуту TEXT:

SELECT id, title FROM pages WHERE title SMATCH '*Embedded*'

Для исполнения этого SQL-запроса потребовалось 35,314 сек.

Оказалось, что поиск через индекс в СУБД Empress происходит в 500 раз быстрее, чем исполнение SQL-запроса!