Snapshot Queries

Snapshot mode allows you to get the advantages of the Lazy queries avoiding their side effects. When query is executed, the query processor chooses the best indexes, does all index processing and creates a snapshot of the index at this point in time. Non-indexed constraints are evaluated lazily when the application iterates through the ObjectSet resultset of the query.

QueryModesExample.cs: TestSnapshotQueries
01public static void TestSnapshotQueries() 02 { 03 Console.WriteLine("Testing query performance on 10000 pilot objects in Snapshot mode"); 04 FillUpDB(10000); 05 IObjectContainer db = Db4oFactory.OpenFile(YapFileName); 06 try 07 { 08 db.Ext().Configure().Queries().EvaluationMode(QueryEvaluationMode.SNAPSHOT); 09 IQuery query = db.Query(); 10 query.Constrain(typeof(Pilot)); 11 query.Descend("_points").Constrain(99).Greater(); 12 DateTime dt1 = DateTime.UtcNow; 13 query.Execute(); 14 DateTime dt2 = DateTime.UtcNow; 15 TimeSpan diff = dt2 - dt1; 16 Console.WriteLine("Query execution time=" + diff.Milliseconds + " ms"); 17 } 18 finally 19 { 20 db.Close(); 21 } 22 }
 


QueryModesExample.vb: TestSnapshotQueries
01Public Shared Sub TestSnapshotQueries() 02 Console.WriteLine("Testing query performance on 10000 pilot objects in Snapshot mode") 03 FillUpDB(10000) 04 Dim db As IObjectContainer = Db4oFactory.OpenFile(YapFileName) 05 Try 06 db.Ext.Configure.Queries.EvaluationMode(QueryEvaluationMode.SNAPSHOT) 07 Dim query As IQuery = db.Query 08 query.Constrain(GetType(Pilot)) 09 query.Descend("_points").Constrain(99).Greater() 10 Dim dt1 As DateTime = DateTime.UtcNow 11 query.Execute() 12 Dim dt2 As DateTime = DateTime.UtcNow 13 Dim diff As TimeSpan = dt2 - dt1 14 Console.WriteLine("Query execution time=" + diff.Milliseconds.ToString() + " ms") 15 Finally 16 db.Close() 17 End Try 18 End Sub
 


Snapshot queries ensure better performance than Immediate queries, but the performance will depend on the size of the resultset.

As the snapshot of the results is kept in memory the result set is not affected by the changes from the caller or from another transaction (compare the results of this code snippet to the one from Lazy Queries topic):

QueryModesExample.cs: TestSnapshotConcurrent
01public static void TestSnapshotConcurrent() 02 { 03 Console.WriteLine("Testing snapshot mode with concurrent modifications"); 04 FillUpDB(10); 05 IObjectContainer db = Db4oFactory.OpenFile(YapFileName); 06 try 07 { 08 db.Ext().Configure().Queries().EvaluationMode(QueryEvaluationMode.SNAPSHOT); 09 IQuery query1 = db.Query(); 10 query1.Constrain(typeof(Pilot)); 11 query1.Descend("_points").Constrain(5).Smaller(); 12 IObjectSet result1 = query1.Execute(); 13 14 IQuery query2 = db.Query(); 15 query2.Constrain(typeof(Pilot)); 16 query2.Descend("_points").Constrain(1); 17 IObjectSet result2 = query2.Execute(); 18 Pilot pilotToDelete = (Pilot)result2[0]; 19 Console.WriteLine("Pilot to be deleted: " + pilotToDelete); 20 db.Delete(pilotToDelete); 21 Pilot pilot = new Pilot("Tester", 2); 22 Console.WriteLine("Pilot to be added: " + pilot); 23 db.Set(pilot); 24 25 Console.WriteLine("Query result after changing from the same transaction"); 26 ListResult(result1); 27 } 28 finally 29 { 30 db.Close(); 31 } 32 }
 

QueryModesExample.vb: TestSnapshotConcurrent
01Public Shared Sub TestSnapshotConcurrent() 02 Console.WriteLine("Testing snapshot mode with concurrent modifications") 03 FillUpDB(10) 04 Dim db As IObjectContainer = Db4oFactory.OpenFile(YapFileName) 05 Try 06 db.Ext.Configure.Queries.EvaluationMode(QueryEvaluationMode.SNAPSHOT) 07 Dim query1 As IQuery = db.Query 08 query1.Constrain(GetType(Pilot)) 09 query1.Descend("_points").Constrain(5).Smaller() 10 Dim result1 As IObjectSet = query1.Execute 11 Dim query2 As IQuery = db.Query 12 query2.Constrain(GetType(Pilot)) 13 query2.Descend("_points").Constrain(1) 14 Dim result2 As IObjectSet = query2.Execute 15 Dim pilotToDelete As Pilot = CType(result2(0), Pilot) 16 Console.WriteLine("Pilot to be deleted: " + pilotToDelete.ToString()) 17 db.Delete(pilotToDelete) 18 Dim pilot As Pilot = New Pilot("Tester", 2) 19 Console.WriteLine("Pilot to be added: " + pilot.ToString()) 20 db.Set(pilot) 21 Console.WriteLine("Query result after changing from the same transaction") 22 ListResult(result1) 23 Finally 24 db.Close() 25 End Try 26 End Sub
 

Pros and Cons for Snapshot Queries

Pros:

  • Index processing will happen without possible side effects from changes made by the caller or by other transaction.
  • Since index processing is fast, a server will not be blocked for a long time.

Cons:

  • The entire candidate index will be loaded into memory. It will stay there until the query ObjectSet is garbage collected. In a C/S setup, the memory will be used on the server side

Client/Server applications with the risk of concurrent modifications should prefer Snapshot mode to avoid side effects from other transactions.