Wednesday, February 22, 2012
   
Text Size

Site Search powered by Ajax

Lesson 5 - Universe Indexes Part 2

Giving UniVerse Secondary Indexes a Second Chance

Type 25 (B-tree) Files

Secondary Indexes are implemented using Type 25 (B-tree) Files. The records in a type 25 file are stored in sorted order, not hashed like Types 2-18 and 30. These files can be read or written just like others, or they can be browsed forwards and backwards, and they are extremely efficient.  The files are implemented using a structure called a B-tree.  There are a number of theories about what the B in B-tree stands for – I’ve heard Binary and Boeing, but the UniVerse documentation uses the term Balanced.  This balancing and managing concurrent updates and reads adds a great deal of complexity to the B-tree file structure.  We pay a penalty in terms of disk space – 300% overhead seems to be a minimum – but we get a reliable index that's built in to the database engine.  The indexes are always in synch with the data.   Note that there were issues with Type 25 files before release 9.6, but the product is considered very stable currently.

The CREATE.INDEX command

When we issue a create.index command, UniVerse creates an index directory (I_filename) containing an index map file and one file for each index.  It imbeds the path to this index directory in the header of the original data file; this ensures that F-pointers to this file will inherit all the indexes.   Let's look at a session:

 >CREATE.INDEX STUDENT TEACHER.ID>SELECT STUDENT WITH TEACHER.ID EQ "1" REQUIRE.INDEXUnable to use alternate keys when required.>DOSMicrosoft Windows 2000 [Version 5.00.2195](C) Copyright 1985-2000 Microsoft Corp. e:\uv>cd I_STUDENT E:\uv\I_STUDENT>dir Volume in drive E has no label. Volume Serial Number is BC04-DD8D  Directory of E:\uv\I_STUDENT 08/22/2002  07:55p      <DIR>          .08/22/2002  07:55p      <DIR>          ..08/22/2002  07:55p              16,384 INDEX.00008/22/2002  07:55p                  31 INDEX.MAP               2 File(s)         16,415 bytes E:\uv\I_STUDENT>type INDEX.MAPINDEX.000         TEACHER.IDDSNYY1>LIST.INDEX STUDENT TEACHER.IDAlternate Key Index Summary for file STUDENTFile........... STUDENTIndices........ 1 (0 A-type, 0 C-type, 1 D-type, 0 I-type, 0 SQL, 0 SIndex Updates.. Enabled, No updates pending Index name      Type  Build    Nulls  In DICT  S/M  Just Unique FieldTEACHER.ID       D    Required  Yes    Yes      S    L     N    1>SET.INDEX STUDENT INFORMIndices for file "STUDENT" reside in "e:/uv/I_STUDENT".  

Just issuing the create.index command doesn't make the index useable.  When we add a require.index clause to our select, it fails.

 

If we shell out to the operating system level and look at the newly created I_STUDENT directory we see two files: INDEX.000 – the type 25 file that will contain the index; and INDEX.MAP – a special file containing information on all the indexes associated with the file STUDENT.

 

This information is summarized in the list.index command output.  Note that the Index Updates status is "Enabled" – this is misleading, changes to the data file are not reflected  in the index until it is built.

 

The set.index command is used to display or update the index path in the file header.

The BUILD.INDEX command

The build.index command locks the data file, selects it, and processes the records one at a time building the index.  If you try to set an item lock on the data file while the build is underway, you'll get an error.  Let's look at a session:

 >BUILD.INDEX STUDENT TEACHER.ID Locking 'STUDENT' file for exclusive use.Starting SSELECT for file 'STUDENT index TEACHER.ID'.Compiling "@INDEX.TEACHER.ID".@Ak.0 ; @1 : ( char ( 251 ) ) : @Ak.ID 1 record(s) selected to SELECT list #0. Clearing Index File INDEX.000 Starting DATA processing for index 'TEACHER.ID'!               1 total processed. Updating INDEX.MAP flags...  Index build of TEACHER.ID complete. File 'STUDENT' Unlocked.  >SELECT STUDENT WITH TEACHER.ID EQ "1" REQUIRE.INDEX 1 record(s) selected to SELECT list #0.>> >LIST.INDEX STUDENT TEACHER.IDAlternate Key Index Summary for file STUDENTFile........... STUDENTIndices........ 1 (0 A-type, 0 C-type, 1 D-type, 0 I-type, 0 SQL, 0 SIndex Updates.. Enabled, No updates pending Index name      Type  Build    Nulls  In DICT  S/M  Just Unique Field

TEACHER.ID       D    Not Reqd  Yes    Yes      S    L     N    1

 

The build.index command can take hours or days for large files with complex index keys.  During this time the data file has read-only access.  There may be a way around this using temporary files and the set.index command, discussed later.

SELECTing Indexes

The drawback to using an index instead of an explicit list of detail items in the header record is that the two traditional techniques used to get a list of detail keys for a given header item are not "header centric."  They involve a select against the detail file. In order to access the list of detail keys, there are two documented methods:

 

TCL

SELECT STUDENT WITH TEACHER.ID EQ "X"
BASICSELECTINDEX "TEACHER.ID","X" FROM FILE.STUDENT TO LIST.VAR
 

We could wrap either one of these selects in a subroutine called from an I-descriptor:

 
I Getting keys the old waySUBR("TEACHER.TO.STUDENT",TEACHER.ID)
  
SUBROUTINE TEACHER.TO.STUDENT (STUDENT.IDS, TEACHER.ID)** Returns a list of STUDENT keys for a supplied TEACHER id.* Version 1 – carrying around a file pointer*COMMON /TEACHER.TO.STUDENT/OPEN.FILE,FILE.STUDENT*LIST.VAR = 9RESULT = ""IF NOT(OPEN.FILE) THEN   OPEN "","STUDENT" TO FILE.STUDENT ELSE RETURN   OPEN.FILE = @TRUEEND*SELECTINDEX "TEACHER.ID",TEACHER.ID FROM FILE.STUDENT TO LIST.VARSTUDENT.IDS = ""LOOP  READNEXT STUDENT.ID FROM LIST.VAR ELSE EXIT  STUDENT.IDS<1,-1> = STUDENT.IDREPEATRETURN
  
SUBROUTINE TEACHER.TO.STUDENT (STUDENT.IDS, TEACHER.ID)** Returns a list of STUDENT keys for a supplied TEACHER id.* Version 2 – no files but expensive execute*COMMAND = "SELECT STUDENT WITH TEACHER.ID EQ " : TEACHER.IDEXECUTE COMMAND CAPTURING MESSAGE*STUDENT.IDS = ""LOOP  READNEXT STUDENT.ID ELSE EXIT  STUDENT.IDS<1,-1> = STUDENT.IDREPEATRETURN
  

These are the traditional ways to deal with Secondary Files programmatically.  Apart from the complexity, there exists a danger that someone else will be using the select list you’ve chosen.  It is especially important when we’re using an I-descriptor; who knows what select lists will be active when this I-descriptor is eventually used.

Accessing Index Files Directly

We can create a file pointer to the actual type 25 file containing the index.  This file will be located in a directory I_filename (in this case I_STUDENT) in the UniVerse account where the index was created.  The easiest way to do this is to do a CREATE.FILE DICT STUDENT_TEACHER.ID and edit the new VOC item to replace attribute 2 with I_STUDENT/INDEX.000. This is documented in the UniVerse File Structures chapter of the UniVerse System Description manual.

 
I Getting keys the newer waySUBR("TEACHER.TO.STUDENT,@ID)
 

Newest Jobs

Universe DBA
Company: Eltas Enterprises, INC
Category: Computer/IT
Type: Internship
Posted: July 14, 2010


Our Sponsors

55°
13°
°F | °C
Overcast
Humidity: 86%
Wind: W at 12 mph
Wed

54 | 70
12 | 21
Thu

57 | 72
13 | 22
Fri

32 | 66
0 | 18
Sat

32 | 54
0 | 12