Page 1 of 2

Filtering data in a DBF-file

PostPosted: Fri Mar 04, 2011 10:12 am
by driessen
ello,

I'm looking for an alternative for "SET FILTER TO".

I have some very huge DBF-files and using "SET FILTER TO" is soooooo slow.

You may think : why don't you use an index in the CDX-file ? I can't use an index as such because there are so many possibilities that that data need to be filtered. It is just impossible to build a tag in the CDX-file for any possibility.

Anyone any idea ?

Thanks.

Re: Filtering data in a DBF-file

PostPosted: Fri Mar 04, 2011 10:41 am
by MarcoBoschi
Please,
write some examples of SET FILTER TO you have to do

Other questions:

- from one table?
- from several related tables ?
- in Lan?
- directly in a local volume?

bye

Re: Filtering data in a DBF-file

PostPosted: Fri Mar 04, 2011 10:53 am
by PeterHarmes
I create a scope that will filter most of the data (for example, if it was a transaction file, scope on start/end date) then create an index using the USECURRENT parameter.

Dont know if you can use something like that?

Best regards,

Pete

Re: Filtering data in a DBF-file

PostPosted: Fri Mar 04, 2011 11:14 am
by kokookao2007
hi:
What is your RDD ?
What did you do after Filter ? only browse ? Need edit ?

1)RDD "DBFCDX: CAN FILTER MORE THAN 2 TRY TO

SET SCOPE TO aaa
SET FILTER TO &cCond

2)RDD "ADS": I don't Know how to filter more than one table.

SET SCOPE TO aaa
SET FILTER TO &cCond ==>need tansfer to AdsSetAof( <xpr> )

My customer has a dbf file with 5 index files,4 relation file more 2GB , still work .

Woule you give your sample?

--
Best Regards
--------------------------------------------------------------
kokoo

Re: Filtering data in a DBF-file

PostPosted: Fri Mar 04, 2011 12:05 pm
by driessen
Hello guys,

Thanks a lot for your answer.

Here is my example :
Code: Select all  Expand view
cFilt := "(AG->AGDATUM = US->UPRDATV" + IF(US->UVERTODO,")"," .OR. (AG->AGDATUM < US->UPRDATT .AND. !AG->AGAFGESL .AND. AG->AGAGRAP))")

IF UPPER(ALLTRIM(UsTab[LEN(UsTab)])) <> "ALLE GEBRUIKERS"
   cFilt += " .AND. ("
   FOR i=1 TO LEN(UsTab)
       cFilt += ("VAL(AG->AGUSER) = " + ALLTRIM(RIGHT(UsTab[i],7)))
       IF i <> LEN(UsTab) ; cFilt += " .OR. " ; ENDIF
   NEXT
   cFilt += ")"
ENDIF

//Order key = "AGUSERNS+AGUSER+LEFT(AGBTIJD,2)+RIGHT(AGBTIJD,2)+LEFT(AGETIJD,2)+RIGHT(AGETIJD,2)+DTOS(AGDATUM)"

SELECT AG
SET ORDER TO 21
SET FILTER TO &cFilt
 
It works very well, but soooo slowly.

The order key :

AGUSERNS = name of person
AGUSER = the person's internal code (C 7)

The order has to be that way because I need to make calculations per person and per day and the result has to be shown alphabetically.

Thanks a lot in advance for your help.

Re: Filtering data in a DBF-file

PostPosted: Fri Mar 04, 2011 12:15 pm
by PeterHarmes
I would create a scope on AGDATUM - then index on AGUSERNS + AGUSER USECURRENT FOR UserFunc()

UserFunc would be your filter condition returning .T./.F.

If there is still a long delay, you could display a progress bar using EVAL ... so that your users can see that something is happening - although i have found that indexing is quicker without the EVAL

Hope that helps!!

Re: Filtering data in a DBF-file

PostPosted: Fri Mar 04, 2011 1:15 pm
by driessen
Peter,

Thanks a lot for your answer.

But how can I use another index when I have created a scope on AGDATUM ?

How does USERCURRENT FOR UserFunc() work ?

Can you give me an example of displaying a progress bar by using EVAL ?

Thanks a lot.

Re: Filtering data in a DBF-file

PostPosted: Fri Mar 04, 2011 2:04 pm
by MarcoBoschi
Driessen,
I've made this little test:

ANNOUNCE RDDSYS

FUNCTION MAIN()

SET DELETED ON
SET EXCLUSIVE OFF

SELECT 0
USE clihs
SET INDEX TO clihs

? SECONDS()
INDEX ON clifor TAG CLIFOR TO filtrato FOR prov = "PD" .AND. SUBSTR( clifor , 1 , 2 ) = "AB"
? SECONDS()

RETURN NIL

INIT PROCEDURE RddInit
REQUEST DBFFPT
REQUEST DBFCDX
rddSetDefault( "DBFCDX" )
RETURN

In my client it takes 6" to create index

seconds() 54020.32
seconds() 54026.31

In my server it takes exactly 0,13 seconds !!!! Just a blink!

seconds() 53999.42
seconds() 53999.55

Continue to use the SET FILTER but the server is a good choice
Bye

Re: Filtering data in a DBF-file

PostPosted: Fri Mar 04, 2011 2:09 pm
by PeterHarmes
Driessen,

Here is an example of creating an index using USECURRENT and progress bar:

Note - CmxKeyCount() is dbOrderInfo(DBOI_KEYCOUNTRAW, cBag, xOrder) - I used to use comix!

Code: Select all  Expand view


//Create Scope

MsgMeter( { | oMeter, oText, oDlg, lEnd | BSeekIndex( oMeter, oText, oDlg, @lEnd ) } )

STATIC FUNCTION BSeekIndex( oMeter, oText, oDlg, lEnd )
    Local TmpIndx := ""
    Private IndxCount := 0
    oMeter:nTotal := BROKERED->(CmxKeyCount())

    CursorWait()

    TmpIndx := TempPath()+"BRKSEEK.CDX"
    IF FILE(TmpIndx)
        FERASE(TmpIndx)
    ENDIF                
    TmpIndx := TempPath()+"BRKSEEK"

    SELECT BROKERED
    INDEX ON STR(SITE_ID,2,0)+ORDER_NO+STR(LINE_NO,4) TO &TmpIndx. FOR !DELETED() .AND. BrokSeekVal() USECURRENT EVAL ( IndxCount++, oMeter:Set( IndxCount ), SysRefresh(), ! lEnd )
    SET INDEX TO &TmpIndx.
    CursorArrow()
RETURN NIL

 


My function BrokSeekVal then filters the data:
Code: Select all  Expand view

FUNCTION BrokSeekVal
    LOCAL RetVal := .T.
    IF !Empty(mCustFrom) .OR. !Empty(mCustTo)
        RetVal := LEFT(BROKERED->ACNT_NBR,LEN(ALLTRIM(mCustFrom))) >= Alltrim(mCustFrom) .AND. ;
                LEFT(BROKERED->ACNT_NBR,LEN(ALLTRIM(mCustTo))) <= Alltrim(mCustTo)
    ENDIF
    IF RetVal .AND. ;
        (!Empty(mGradeFrom) .OR. !Empty(mGradeTo))
        RetVal := LEFT(BROKERED->GRADE,LEN(ALLTRIM(mGradeFrom))) >= Alltrim(mGradeFrom) .AND. ;
                LEFT(BROKERED->GRADE,LEN(ALLTRIM(mGradeTo))) <= Alltrim(mGradeTo)
    ENDIF
    IF RetVal .AND. ;
        (!Empty(mOrdFrom) .OR. !Empty(mOrdTo))
        RetVal := LOWER(LEFT(BROKERED->CUST_ORDER,LEN(ALLTRIM(mOrdFrom)))) >= Lower(Alltrim(mOrdFrom)) .AND. ;
                LOWER(LEFT(BROKERED->CUST_ORDER,LEN(ALLTRIM(mOrdTo)))) <= Lower(Alltrim(mOrdTo))
    ENDIF
    IF RetVal .AND. ;
        (!Empty(mPurchFrom) .OR. !Empty(mPurchTo))
        RetVal := LEFT(BROKERED->PURCH_CUST,LEN(ALLTRIM(mPurchFrom))) >= Alltrim(mPurchFrom) .AND. ;
                LEFT(BROKERED->PURCH_CUST,LEN(ALLTRIM(mPurchTo))) <= Alltrim(mPurchTo)
    ENDIF
    IF RetVal .AND. ;
        (!Empty(mTranspFrom) .OR. !Empty(mTranspTo))
        RetVal := LEFT(BROKERED->HAULIER,LEN(ALLTRIM(mTranspFrom))) >= Alltrim(mTranspFrom) .AND. ;
                LEFT(BROKERED->HAULIER,LEN(ALLTRIM(mTranspTo))) <= Alltrim(mTranspTo)
    ENDIF
RETURN RetVal
 


If you needed to use another index, you will have to swap between indexes using dbsetorder - but obvioulsy the "filter" will only apply to the newly created index.

Re: Filtering data in a DBF-file - SOLVED

PostPosted: Fri Mar 04, 2011 8:47 pm
by driessen
Peter,

Thank you very, very much.

Your suggestion by building a second CDX-file (which can be build locally) is working fantastically.

Very fast.

I never have used SET INDEX TO. Much better than filtering.

I'm very greatful to you.

Re: Filtering data in a DBF-file

PostPosted: Fri Mar 04, 2011 11:43 pm
by Gale FORd
Don't forget you can add the "Temporary" argument to the index on command. It will automatically create a temporary index and erase it when you are done.

Re: Filtering data in a DBF-file

PostPosted: Tue Mar 08, 2011 9:20 am
by PeterHarmes
No probem, glad I could help.

Gale, I never knew about the TEMPORARY argument, I can imagine that if it creates it in memory the index creation would be faster than writing to disk, but I assume this should only be done on small databases or small selection criteria

Best regards,

Pete

Re: Filtering data in a DBF-file

PostPosted: Tue Mar 08, 2011 2:33 pm
by Gale FORd
It does not automatically create it in memory but I think it depends on the RDD. Here is a brief description of that option.

TEMPORARY
If this option is specified, a temporary index is created which is automatically destroyed when the index is closed. The temporary index may be created in memory only or in a temporary file. This lies in the responsibility of the RDD used for index creation.
For me it creates the temp index in the user folder in c:\documents and settings.

Re: Filtering data in a DBF-file

PostPosted: Tue Mar 08, 2011 2:41 pm
by PeterHarmes
Have you ever tried it in a Citrix environment?

Re: Filtering data in a DBF-file

PostPosted: Tue Mar 08, 2011 6:00 pm
by Gale FORd
Yes, I use it all the time. Each user has its own profile location.