=======================================================================
     PUTTING IHASH TO WORK       
     =======================================================================
     PRODUCT:  R:BASE       VERSION :  3.1A Or Higher
     =======================================================================
     AREA   :  PROGRAMMING  CATEGORY:  TEXT SEARCHES         DOCUMENT#: 668
     =======================================================================
 
 
     From:  Royal E. Harris, C.N.E.
            Crowley Maritime Corp.
            14018 4th Ave. East
            Tacoma, WA 98445
            (206) 537-8977
 
     
     Did you ever have a problem with the execution speed of an 
     application, and it wasn't that the speed was too fast?  You set up
     indexes, verified uniqueness, tinkered with memory, upgraded CPU's,
     installed the latest network OS, and still weren't satisfied with the
     performance?  As a last resort did you look through past issues of
     the R:BASE Exchange and you actually find something that might solve
     the problem?
 
     The problem
     -----------
     Here was just such a situation.  A customer table search had run
     amuck.  My mission?  Speed the search up.  As the network manager,
     transporting a multi user database, I desired to allow users (armed
     with only the customer's name) to select and edit a particular
     customer file.  No tacked up lists of customer identification numbers
     allowed.  All that our users need to know is the alphabet well enough
     to partially spell a name.
 
     The customer table has two indexed columns: FINDNAME column (TEXT 50)
     and a CUSTNUM (TEXT 10).  As the names suggest, the FINDNAME column
     is made up of last & first names, and the CUSTNUM column is a
     customer number. The application instructs the user to enter one or
     more letters of the customer name; then, using the CHOOSE command to
     pop-up a menu, pick which customer to edit.
 
     Here is the original code:
 
      SET MANY=*
      SET VAR vsearch TEXT vcustnum TEXT
      FILLIN vsearch USING "Enter customer search text: " at 9 6 REVERSE
      SET VAR vsearch = .vsearch + "*"
      CHOOSE shown FROM #VALUES FOR FINDNAME FROM CUSTOMER WHERE +
          FINDNAME LIKE .vsearch ORDER BY FINDNAME ASC CLEAR
      CLEAR VAR vsearch
      SET VAR vcustnum = CUSTNUM IN CUSTOMER WHERE FINDNAME = .shown
      EDIT USING FORMNAME WHERE CUSTNUM = .vcustnum
 
     This worked well.  An "H" entered displayed all customers with a
     FINDNAME beginning with "H", and "HA" displayed only those customers
     with FINDNAMES beginning "HA", and so on.  The user need only know
     names, no customer numbers.  It was a good trick until the customer
     list grew, and grew, and grew out of control. 
 
     
     
     
     
     
     
     
     
     Now it only worked, not necessarily well.  The search began to 
     consume full seconds of user time.  It was annoying to wait six 
     seconds for each and every customer edited to appear in the menu. We
     had to find a way to speed up the application or to eliminate
     customers.  Shareholders tend to frown on the latter.
 
     The solution
     ------------
     We are now at the moment of desperation.  I find the July/August 1991
     issue of the "R:BASE Exchange" (v. 8 n. 4),  and see the article
     'Indexes & IHASH Add Speed'.  Every word on pages 14 and 15 of that
     issue is correct, but the article has no direct use to us because our
     WHERE clause contained the LIKE condition. LIKE and integer
     comparisons do not mix; never have, never will.
 
     We can't be telling our users that they must key in the exact 
     customer name (FINDNAME) all the way to 50 characters, if neccessary,
     in the cause of "increased  performance", now can we.  That is 
     exactly what we'd have to do if we intended to use an indexed IHASH 
     column with an '=' condition.  The users were already used to keying 
     an "H", hitting enter, and magically getting all the "Harris"'s in 
     the customer file on their screen.
     
     So I wondered how the IHASH function could possibly be of
     assistance.  It is a simple case of having it both ways,  IHASH
     (integer based performance) and FINDNAME (text based ease of use). 
     The idea may not appear to be extremely elegant, but it is extremely
     robust.  After implementation, the execution of the search is more
     than ten times as fast.  
 
     Two simple steps are involved in implementing the idea.  First, add
     an additional column to the customer table named HFN for 'hashed
     findname'. The HFN column is a computed integer column, 
     (IHASH(FINDNAME,3)), and it is indexed.
 
     Yes, the idea was as simple as 1,2,3.  Courtesy of R:BASE, the first 
     three letters of the FINDNAME column would be hashed.  But didn't 
     that yield duplicates in the HFN column, you know, many "Harris"'s?  
     Of course it did, but remember, we're using the CHOOSE command to
     provide a choice.  But what if the user doesn't know the first three
     letters of the FINDNAME he wants to edit? What if he only knows one
     letter; ie "H"?
 
     We solved this dilemna with a little R:BASE slight of hand.  We let 
     the one letter users find the customers they want to edit in the usual 
     six second fashion, the users who know three letters, get the speed.  
     This brings us to the second of the two steps, the revised 
     application code:
 
      SET MANY=*
      SET VAR vsearch TEXT vcustnum TEXT
      FILLIN vsearch USING "Enter customer search text: " at 9 6 REVERSE
      IF_(SLEN(.vsearch)) = 3 THEN
        SET VAR vsearch = (IHASH(.vsearch,3))
        CHOOSE shown FROM #VALUES FOR FINDNAME FROM CUSTOMER WHERE +
          HFN = .vsearch ORDER BY FINDNAME ASC CLEAR
      ELSE
        SET VAR vsearch = .vsearch + "*"
        CHOOSE shown FROM #VALUES FOR FINDNAME FROM CUSTOMER WHERE +
          FINDNAME LIKE .vsearch ORDER BY FINDNAME ASC CLEAR
      ENDIF
      
      
      
      
      
      CLEAR VAR vsearch
      SET VAR vcustnum = CUSTNUM IN CUSTOMER WHERE FINDNAME = .shown
      EDIT USING FORMNAME WHERE CUSTNUM = .vcustnum
 
     The users are delighted with the gain in performance, and they can
     still be as precise or as vague as they please with the customer
     name.  They are mostly using the first three alpha characters to
     identify which customer to edit, however, because of the speed.  Here
     is a pleasant R:BASE solution to a speed dilema.