When a space looks for a match for a read or take operation, it iterates over non-null values in the template, looking for matches in the space. This process can be time consuming, especially when there are many potential matches. To improve performance, it is possible to index one or more properties. The space maintains additional data for indexed properties, which shortens the time required to determine a match, thus improving performance.
Choosing which Properties to Index
One might wonder why properties are not always indexed, or why all the properties in all the classes are not always indexed. The reason is that indexing has its downsides as well:
An indexed property can speed up read/take operations, but might also slow down write/update operations.
An indexed property consumes more resources, specifically memory footprint per entry.
When to Use Indexing
Usually it is recommended to index properties that are used in common queries. However, in some scenarios one might favor a smaller memory footprint, or faster performance for a specific query, and adding/removing an index should be considered.
Remember that "Premature optimization is the root of all evil." It is always recommended to benchmark your code to get better results.
Index Types
The index type is determined by the SpaceIndexType enumeration. The index types are:
None - No indexing is used. Basic - Basic index is used - which speeds up equality matches (equal to/not equal to). Extended - Extended index - which speeds up relative matches (bigger than/less than).
Indexing at Design-time
Specifying which properties of a class are indexed is done using attributes or gs.xml.
Annotations
[SpaceClass]
public class Person
{
...
[SpaceIndex(Type=SpaceIndexType.Basic)]
publicString FirstName{ get; set;}
[SpaceIndex(Type=SpaceIndexType.Basic)]
publicString LastName{ get; set; }
[SpaceIndex(Type=SpaceIndexType.Extended)]
publicint? Age{ get; set; }
}
By default, a property's index is inherited in sub classes (i.e. if a property is indexed in a super class, it is also indexed in a sub class). If you need to change the index type of a property in a subclass you can override the property and annotate it with [SpaceIndex] using the requested index type (to disable indexing use None).
Indexing at Run-time
Indexes can be added dynamically at run-time using the GigaSpaces Management Center GUI.
Removing an index or changing an index type is currently not supported.
Nested Properties Indexing
An index can be defined on a nested property to improve performance of nested queries - this is highly recommended.
Nested properties indexing uses an additional [SpaceIndex] attribute - Path.
The SpaceIndex.Path Attribute
The Path attribute represents the path of the property within the nested object.
Below is an example of defining an index on a nested property:
Single Index Annotation
[SpaceClass]
public class Person
{
//Properties
...
// this defines and Extended index on the PersonalInfo.SocialSecurity property
[SpaceProperty(StorageType = StorageType.Document)]
[SpaceIndex(Path = "SocialSecurity", Type = SpaceIndexType.Extended)]
public Info PersonalInfo{ get; set; }
}
public class Info
{
publicString Name {get; set;}
public Address Address {get; set;}
public DateTime Birthday {get; set;}
publiclong SocialSecurity {get; set;}
publicint Id;
}
public class Address
{
privateint ZipCode {get; set;}
privateString Street {get; set;}
}
Multiple Indexes Annotation
[SpaceClass]
public class Person
{
//Properties
...
// this defines several indexes on the same personalInfo property
[SpaceIndex(Path = "SocialSecurity", Type = SpaceIndexType.Extended)]
[SpaceIndex(Path = "Address.ZipCode", type = SpaceIndexType.Basic)})
[SpaceProperty(StorageType = StorageType.Document)]
public Info PersonalInfo{ get; set; }
// this defines indexes on map keys
[SpaceIndex(Path = "Key1", Type = SpaceIndexType.Basic)]
[SpaceIndex(Path = "Key2", Type = SpaceIndexType.Basic)]
public Dictionary<String, String> Table{ get; set; }
}
The following is an example of query code that automatically triggers this index:
SqlQuery<Person> query = new SqlQuery<Person>(
"PersonalInfo.SocialSecurity<10000050L and PersonalInfo.SocialSecurity>=10000010L");
Nested Objects By default, nested objects are kept in a binary form inside the space. In order to support nested matching, the relevant property should be stored as document, or as object if it is in an interoperability scenario and it has a corresponding Java class.
Dictionary based nested properties Note that the same indexing techniques above are also applicable to Dictionary-based nested properties, which means that in the example above the Info and Address classes could be replaced with a Dictionary<String,Object>, with the dictionary keys representing the property names.
Collection Indexing
An index can be defined on a Collection property (such as List). Setting such an index means that each of the Collection's items is indexed.
Setting an index on a Collection is done using the SpaceIndex.Path attribute where a Collection property should be followed by "[*]".
The following example shows how to define an index on a List of Integers:
[SpaceClass]
public class CollectionIndexingExample
{
privateInteger id;
private List<int> numbers;
// Getter and setter methods...
// This means that each Integer in the List is indexed.
[SpaceIndex(Path="[*]")]
public List<int> Numbers { get; set; }
}
The following query shows how to take advantage of the defined index:
SqlQuery<CollectionIndexingExample> sqlQuery =
new SqlQuery<CollectionIndexingExample>("Numbers[*] = 30");
CollectionIndexingExample[] result = spaceProxy.ReadMultiple(sqlQuery);
Nested property within a Collection
Its also possible to index a nested property within a collection.
The following example shows how to define an index on a Book.id property, which resides in a Collection property in Author:
[SpaceClass]
public class Author
{
// Properties...
// This means that each Book.Id in the Collection is indexed.
[SpaceIndex(Path = "[*].Id")]
[SpaceProperty(StorageType = StorageType.Document)]
public List<Book> Books{ get; set; }
}
public class Book
{
// Properties...
publicint? Id{ get; set; }
}
The following query shows how to take advantage of the defined index:
SqlQuery<Author> sqlQuery = new SqlQuery<Author>("Books[*].Id = 57");
Author result = spaceProxy.Read(sqlQuery);
Setting an index on a Collection within a nested property is also accepted:
[SpaceClass]
public class Employee
{
// Properties...
[SpaceIndex(Path = "PhoneNumbers[*]")]
[SpaceProperty(StorageType = StorageType.Document)]
public Information Information{ get; set; }
}
public class Information
{
// Properties...
public List<String> PhoneNumbers{ get; set; }
}
Both [SpaceIndex(Type=SpaceIndexType.Basic)] and [SpaceIndex(Type=SpaceIndexType.Extended)] are supported.
Query Execution Flow
When a read, take, read multiple, or take multiple call is performed, a template is used to locate matching space objects. The template might have multiple field values - some might include values and some might not (i.e. null field values acting as wildcard). The fields that do not include values are ignored during the matching process. In addition, some class fields might be indexed and some might not be indexed.
When multiple class fields are indexed, the space looks for the field value index that includes the smallest amount of matching space objects with the corresponding template field value as the index key.
The smallest set of space objects is the list of objects to perform the matching against (matching candidates). Once the candidates space object list has been constructed, it is scanned to locate space objects that fully match the given template - i.e. all non-null template fields match the corresponding space object fields.
Class fields that are not indexed are not used to construct the candidates list.