Saturday, February 1, 2014

LOCATE vs SEEK, which is faster?

From time to time someone would inquire which is faster?  LOCATE or SEEK? And the answer mostly is it depends, if the records are small, then the speed difference is negligible enough.  True.  But that does not still answer which really is faster.  When we say faster, it has to be at least a nanosecond quicker than the other one.  We are not arguing "how" fast but "which" is faster.



To understand better which is really faster, we have to first understand how the two differs.  How does LOCATE performs searching?  How does SEEK performs searching?  Let us start with SEEK() first.

HOW DOES SEEK() PERFORM SEARCHING?

In order for SEEK() to properly kick in, you have to have an index on field(s) where you wanted to search for a match.  An index can be structural (part of the table in the form of a cdx extension, auto-opens with the table) or non-structural (stand-alone idx file, does not auto-open with table, can be re-used or discarded later).

With SEEK(), when you search a value, it performs a Binary Search on its index file where it jumps outright to the middle, compares the value being searched and if value of the record is over, goes to the upper half and performs the same again (breaks it in the middle again and checks). If value is less, goes to the bottom part, does the same too, breaks it in half.

The process is repeated over and over again until it finds the match, or not, and positions itself  in EOF or onto another record, based on SET NEAR and SET EXACT settings.


HOW DOES LOCATE PERFORM SEARCHING?

Because LOCATE is designed to work even on non-indexed  (not sorted) field(s), then in some cases it is really useful especially if you wanted two or more fields for comparisons.  But how does LOCATE do it actually on a non-sorted field(s)?

When you perform any LOCATE command, what VFP (and some old xBase apps) do is to immediately position the record at the top and does a sequential search going down.   This can be easily tested like this:

LOCAL lnloop
CREATE CURSOR junk (whatever I)
FOR lnloop = 1 TO 100
  INSERT INTO junk VALUES (m.lnloop)
NEXT
MESSAGEBOX(RECNO())

* Issue locate
LOCATE
MESSAGEBOX(RECNO())

* jump to another record
goto(30)
MESSAGEBOX(RECNO())

* Issue locate
LOCATE
MESSAGEBOX(RECNO())

* jump to another record
goto(85)
MESSAGEBOX(RECNO())

* Issue locate
LOCATE
MESSAGEBOX(RECNO())


So you see, whenever you issue a LOCATE, it immediately positions itself on top of the record.  Why?  What is the reason?  Because LOCATE is designed to allow user to search for a match by always starting from top then performing a sequential search or skipping records one by one until it hits the match you are looking for or it hits EOF().

IS THERE A CASE WHERE LOCATE WILL BE FASTER THAN SEEK?

Yes, if the record that you are looking for is closer to top records in its natural order.  But if it is closer to the middle or bottom records, then it will take much longer to find that via LOCATE.


Summary:

Looking on the way these two search engines work, it is very clear that SEEK() is really faster than LOCATE.  As the records grow, LOCATE will comparatively take longer than SEEK() in searching for a match.

Hope I was able to give a clear explanation on these two.  Cheers!





4 comments:

  1. why are you still teaching about a dead language?

    ReplyDelete
  2. Which? SEEK() and LOCATE command or VFP? If it is VFP, then I am sorry, there are still tons of developers using this one. ;)

    ReplyDelete
  3. Absolutely agree with Mr. Jun. VFP is not a dead language Mr. Anonymous ;) BTW Congratulations Mr. Jun as Ceil Silver Ambassador 2012 at Southwestfox Arizona USA, i hope and wish i could attend the Southwestfox soon.

    ReplyDelete
  4. Absolutely agree with Mr. Jun. VFP is not a dead language. BTW, Congratulations Mr. Jun as 2012 Ceil Silver Ambassador in Southwestfox Arizona. I wish i could attend soon the conference.

    ReplyDelete