4646
Как правильно индексировать в VFP?

 

> А как правильно проиндексировать?

Хм... вопрос конечно интересный. Ладно, попробую ответить.

При создании нового "не составного" индекса по умолчанию его "Название" [Name] (Tag) совпадает с "вычисляемым выражением" [Exspression] ... Однако, индекс должен быть "одно-форматным", и независим от того, как были введены значения в поля (я имею ввиду большие/маленькие буквы). Например: в поле Exspression для индекса прописываем: UPPER(MyField) или LOWER(MyField) или PROPER(MyField)...[общепринято: UPPER(MyField)]

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

В VFP по крайней мере в 6.0 сказанное выше для индексов в случае SET COLLATE TO "RUSSIAN" делается автоматически [т.е.UPPER(MyField), если даже в Exspression явно мы это и не прописываем]... и это может приводить к проблемам :-(  Другими словами, уж лучше писать явно :-)

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

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

Замечания относительно Rushmore оптимизации (в основном цитируя MSDN :-)

Технология основана на оптимизации доступа к данным с помощью использования стандартных VFP-индексов (idx,cdx) и способна резко повысить производительность операций обработки данных за счёт использования оперативной памяти компьютера. Способна уменьшить время выполнения многотабличных запросов если даже индекс создаётся как временный (только на время выполнения запроса).

Если кратко, то оптимизации подвержены команды, содержащие предложение FOR и когда используемые условные выражения представлены в терминах определяющих выражений индексов. В SQL командах для успешной оптимизации не требуется предварительного открытия ни таблиц ни индексов. SQL самостоятельно решает вопрос о необходимости тех или иных индексов и, если они не существуют, создаёт их временными самостоятельно.

Оптимизации отключается для:

все другие типы индексов оптимизируемы.

Для повышения производительность отключайте (SET ORDER TO 0) активные индексы у таблиц (включенные индексы вынуждают выполнять дополнительные, но никому не нужные, действия :-().

Выражения (в Exspression) типа: NOT DELETED() или DISCOUNT > 10   не оптимизируются, хотя оптимизируется например, DELETED() [т.е. INDEX ON DELETED() TAG DEL]

Обратите внимание: при наличии индекса типа: INDEX ON DELETED() TAG DEL в режиме SET DELETED ON оптимизация может быть выполнена.

Если WHERE(FOR) содержит несколько условий соединённых AND или OR, то оптимизации подвергается каждое подвыражения, ...и если нашлось хотя бы одно не оптимизируемое подвыражение при наличии оптимизируемых, то говорят о частичной оптимизации.

Оптимизация не выполняется:

Функция SYS(3054) позволяет контролировать режим оптимизации: None, Partial, Full

Обратите внимание: определяя допустима ли оптимизации в FOR-выражениях, VFP тратит некоторое время, ... и если Вам известно, что выражения не оптимизируемы, то это время можно сэкономить, отключив оптимизацию посредством параметра NOOPTIMIZE или команды SET OPTIMIZE OFF

Оптимизация производится над базовым выражением

eIndex relOp eExp
-или-
eExpr relOp eIndex

где

Однако, функции ISBLANK() и EMPTY() не оптимизируются :-(.

Например, если созданы индексы:

каждое из нижеследующих выражений оптимизируемо:

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

STORE "WASHINGTON AVENUE" TO cVar
ADDR = cVar
ADDR = SUBSTR(cVar,8,3)

Совет: чтобы быть 100% уверенным в каждом конкретном случае используйте функцию SYS(3054) для контроля... см. также "Q156551 HOWTO: Use SYS(3054) to Optimize a Query" (http://support.microsoft.com/kb/q156551/)

> как правильно воспользоваться параметром ORDER в SELECT-SQL

Вот пример кода в версии VFP 8.0 (SP1VFP8), который как надеюсь покажет вам, что не следует использовать ключи неопределённой длины:

#DEFINE USE_PROBLEM_TAG	.T.

IF VERSION(5) < 800
	MESSAGEBOX("Sorry, this test for VFP 8.0 (or later) only.")
	RETURN .F.
ENDIF

RAND(-1) 
LOCAL lcCursor as String
lcCursor = "_" + SYS(2015, 2)
CREATE CURSOR (lcCursor) (fld1 I, fld2 I)
IF !USED(lcCursor)
	RETURN .F.
ENDIF
#IF USE_PROBLEM_TAG
	INDEX ON ;
		TRANSFORM(fld1)+'_'+TRANSFORM(fld2) ;
		TAG fld12
#ELSE
	INDEX ON ;
		TRANSFORM(fld1, '@L 9999999999') + TRANSFORM(fld2, '@L 9999999999') ;
		TAG fld12
#ENDIF	

LOCAL lcExact as String
IF SET("Exact") = 'OFF'
	SET EXACT ON
	lcExact = 'OFF'
ELSE
	lcExact = 'ON'
ENDIF	  

LOCAL lnTestValue as Integer
lnTestValue = NewValue() 
INSERT INTO (lcCursor) (fld1, fld2) VALUES (lnTestValue, NewValue())
INSERT INTO (lcCursor) (fld1, fld2) VALUES (lnTestValue, NewValue())

GO TOP
BROWSE NORMAL NOWAIT

LOCAL lcKey as String
#IF USE_PROBLEM_TAG
	lcKey = TRANSFORM(lnTestValue);
		+ '_' + TRANSFORM(NewValue()) 
#ELSE
	lcKey = TRANSFORM(lnTestValue, '@L 9999999999');
		+ TRANSFORM(NewValue(), '@L 9999999999') 
#ENDIF	

IF SEEK(lcKey, lcCursor, 'fld12')
	WAIT WINDOW "*** Found not exist key: '" + lcKey + "' ?!"
ELSE	 
	WAIT WINDOW "Not found key: '" + lcKey + "' !"
ENDIF

USE IN (lcCursor)
IF SET("Exact") # lcExact
	SET EXACT &lcExact
ENDIF

FUNCTION NewValue() as Integer 
	RETURN INT(RAND()*1000000000)
ENDFUNC
Попробуйте выполнить этот код и при USE_PROBLEM_TAG .F. Нужно заметить, что в VFP 9.0 (SP1VFP9) такая ошибка уже ловится на этапе выполнения: Error building key for index "name". (Error 2199).

См. также:

 
 
Hosted by uCoz