- Local time
- Today, 00:28
- Joined
- Feb 19, 2013
- Messages
- 17,439
I've been reviewing the performance of some of my VBA with a view to trying to improve the performance. The code normally works on around 3-4000 records and has been perfectly satisfactory, but now I need to use it on a much larger recordset - circa 100,000 records.
The code creates a nested set and does this by selecting a single record and if found, updates it and if not it resets to look for the next one.
In summary, there are 100,000 records which ultimately are selected once and updated twice.
This process takes about 1 1/2 hours to run and as it works through the dataset it takes longer and longer for each loop. For the first 20000 records the loop is running at a rate of around 200/second or better which is acceptable but by the time the last records are being referenced the rate has dropped to around 15 loops/second. I believe this is due to updating the treelevel index which I don't think I can do anything about - but any suggestions welcome
. TreeLevel has a narrow range of values (typically 9 or 10 reflecting the different levels of the tree) and is initially updated with a negative number which is changed to a positive number when the record is finished with. I've tried updating all the treelevel fields to null before starting and modifying the index to ignore nulls, but this is actually slower.
Reference is often made to the overhead of needing to compile the sql before running, so I modified the above to use a querdef instead
I was surprised to find it took exactly the same amount of time to run. Am I missing something?
The code creates a nested set and does this by selecting a single record and if found, updates it and if not it resets to look for the next one.
Code:
While LftRgt < MaxLft
'select potential child for a parent
sqlStr = "SELECT TOP 1 fplTree_1.EntityPK FROM fplTree INNER JOIN fplTree AS fplTree_1 ON (fplTree.CTable = fplTree_1.PTable) AND (fplTree.ChildFK = fplTree_1.ParentFK) WHERE fplTree.TreeLevel=" & TreeLevel & " AND fplTree_1.TreeLevel=0 AND fplTree.Branch=" & Branch
Set rst = DB.OpenRecordset(sqlStr)
If rst.EOF Then 'there are no children so finish with this parent
sqlStr = "UPDATE fplTREE SET rgt= " & LftRgt & ", TreeLevel = -TreeLevel WHERE Treelevel=" & TreeLevel
DB.Execute (sqlStr)
TreeLevel = TreeLevel + 1
Else 'there is a child so update and set child as new parent
TreeLevel = TreeLevel - 1
DB.Execute ("UPDATE fplTree SET Lft = " & LftRgt & ", TreeLevel = " & TreeLevel & " WHERE EntityPK=" & rst!Entitypk)
End If
LftRgt = LftRgt + 1
Set rst = Nothing
Wend
This process takes about 1 1/2 hours to run and as it works through the dataset it takes longer and longer for each loop. For the first 20000 records the loop is running at a rate of around 200/second or better which is acceptable but by the time the last records are being referenced the rate has dropped to around 15 loops/second. I believe this is due to updating the treelevel index which I don't think I can do anything about - but any suggestions welcome

Reference is often made to the overhead of needing to compile the sql before running, so I modified the above to use a querdef instead
Code:
Set Q1 = DB.CreateQueryDef("", "SELECT TOP 1 fplTree_1.EntityPK FROM fplTree INNER JOIN fplTree AS fplTree_1 ON (fplTree.CTable = fplTree_1.PTable) AND (fplTree.ChildFK = fplTree_1.ParentFK) WHERE fplTree.TreeLevel = TLevel AND fplTree_1.TreeLevel=0 AND fplTree.Branch = " & Branch)
Set prm1TLevel = Q1!TLevel
Set Q2 = DB.CreateQueryDef("", "UPDATE fplTREE SET rgt = LftRgt, TreeLevel = -TreeLevel WHERE Treelevel = TLevel")
Set prm2TLevel = Q2!TLevel
Set prm2LftRgt = Q2!LftRgt
Set Q3 = DB.CreateQueryDef("", "UPDATE fplTree SET Lft = LftRgt, TreeLevel = TLevel WHERE EntityPK = EID")
Set prm3LftRgt = Q3!LftRgt
Set prm3TLevel = Q3!TLevel
Set prm3EntityID = Q3!EID
While LftRgt < MaxLft
prm1TLevel = TreeLevel
Set rst = Q1.OpenRecordset
If rst.EOF Then
prm2TLevel = TreeLevel
prm2LftRgt = LftRgt
Q2.Execute
TreeLevel = TreeLevel + 1
Else
TreeLevel = TreeLevel - 1
prm3TLevel = TreeLevel
prm3LftRgt = LftRgt
prm3EntityID = rst!Entitypk
Q3.Execute
End If
LftRgt = LftRgt + 1
Set rst = Nothing
Wend
I was surprised to find it took exactly the same amount of time to run. Am I missing something?