Starcounter
HomeDownloadDocsCommunity
2.3.1
2.3.1
  • Starcounter Documentation
  • Getting Started
  • Starcounter
    • Collapsing the Stack
      • Complexity and Scalability Tradeoff
      • The Future of Micro-Services
      • 10 Benefits of Collapsing the Stack
    • Integrated Database and Web Server
  • Hello World - Tutorial
    • Create a Database Class
    • Create a Real Time UI
    • First Interactive UI
    • Computed Properties
    • Expense Tracker
    • Cancel and Delete
    • The Next Step
  • Guides
    • Database
      • Database Classes
      • Data manipulation
      • Object Identity and Object References
      • Querying with SQL
      • Data Types
      • Relations
      • Inheritance
      • Sharing data
      • Database Configuration
      • Comparing Database Objects
      • Referential Integrity and Constraints
    • SQL
      • Identifiers
      • Path Expressions
      • Data operators
      • Joins
      • Aggregates
      • Comparisons and Logical Operators
      • Sorting
      • Fetch
      • Offset Key
      • Indexes
      • Literals
      • Query Plan Hints
      • Reserved words
      • Query for Database Classes
      • SQL Isolation Between Applications
    • Transactions
      • Short-Running Transactions
      • Long running transactions
      • Using Transactions
      • Running Background Jobs
      • Commit Hooks
    • Typed JSON
      • JSON-by-example
      • Code-Behind
      • Data Bindings
      • Callback Methods
      • Responding with JSON
      • Accepting JSON in Requests
      • Primitive Arrays and Single Value Types
      • Typed JSON Internals
    • Blendable Web Apps
      • Starcounter MVVM
      • Palindrom
      • Client-Side Stack
      • Sessions
      • HTML Views
      • App Shell
      • Web Components
      • View Attaching
      • View Composing
      • HTML Compositions
      • HTML Views Blending Guidelines
      • Avoiding CSS conflicts
      • Debugging
    • Network
      • HTTP
      • Internal Self Calls
      • Middleware
      • Anonymous or Substitute Handlers
      • URL Aliases and Redirects
      • Network Gateway
      • Static File Server
      • External HTTP Calls
      • WebSocket
      • Avoiding URI conflicts
      • TCP Sockets
      • UDP Sockets
    • Publishing Apps
    • Working with Starcounter
      • Release Channels
      • Starting and Stopping Apps
      • Administrator Web UI
      • Star CLI
      • StarAdmin CLI
      • StarDump CLI
      • Working in Visual Studio
      • Error Log
      • Using HTTPS on NGINX
      • Using HTTPS on IIS
      • Run Starcounter in Production
      • Weaver
      • Investigating App Crashes
      • Configuration Structure
      • Database Refactoring
      • Using Unload/Reload to Modify Database Schema
      • Kernel Questions and Answers
      • Log Files
  • Cookbook
    • Attach an HTTP Request to an Existing Long-Running Transaction
    • Cookie-Based Authentication
    • Timestamp on Object Creation
    • Creating Strongly Typed JSON Collections
    • Migrating From 2.2 to 2.3+
    • Multiple Pages
    • Icons
    • Proposed Project Structure
    • Acceptance Testing with Selenium
    • Requesting a User to Authenticate
    • How to delete unused tables and columns
Powered by GitBook
On this page
  • Introduction
  • Declaring Indexes
  • Checking for Declared Indexes
  • Dropping Indexes
  • Recommendations
  • Index Hints in Queries
  • Derived Indexes
  1. Guides
  2. SQL

Indexes

Introduction

Indexes are essential to reach optimal performance. CREATE INDEX creates indexes and DROP INDEX removes indexes.

Declaring Indexes

Indexes are created with Db.SQL, where query string contains an index declaration and has the form CREATE [UNIQUE] INDEX indexName ON typeName (propertyName [ASC/DESC], ...).

It is recommended to declare indexes before any retrieval query is issued. Note that indexes should be declared outside a transaction scope.

In the examples (1), (2), (3), (4) and (5) below we declare indexes on different properties/columns of the class/table Employee.

(1) CREATE INDEX EmpFirstNameIndex ON Employee (FirstName ASC)

(2) CREATE INDEX EmpLastNameIndex ON Employee (LastName ASC)

(3) CREATE INDEX EmpSalaryIndex ON Employee (Salary)

(4) CREATE INDEX EmpManagerIndex ON Employee (Manager)

(5) CREATE INDEX EmpDepartmentIndex ON Employee (Department)

The default order, used when there is no order declared, is ASC (ascending). The order specified in the index declaration only matters when you want the result set to be sorted (ORDER BY).

You can declare indexes on properties/columns of the following datatypes (DbTypeCode): Boolean, Byte, DateTime, Decimal, Int16, Int32, Int64, Object, SByte, String, UInt16, UInt32, UInt64.

You can declare combined indexes on up to ten different properties/columns of a class/table. In the examples (6), (7), (8) and (9) we have some combined indexes on two properties/columns of the class/table Employee.

(6) CREATE INDEX EmpLastnameFirstNameIndex ON Employee (LastName ASC, FirstName ASC)

(7) CREATE INDEX EmpFirstNameLastNameIndex1 ON Employee (FirstName ASC, LastName ASC)

(8) CREATE INDEX EmpFirstNameLastNameIndex2 ON Employee (FirstName DESC, LastName ASC)

(9) CREATE INDEX EmpDepartmentSalaryIndex ON Employee (Department ASC, Salary DESC)

Checking for Declared Indexes

The indexName must be unique. If you define the same name more than once you will get an exception. It is possible to check if an index was already created by issuing a query, which selects a record from table Starcounter.Metadata.Index with column Name equivalent to the index name as in the example below.

if (Db.SQL("SELECT i FROM Starcounter.Metadata.\"Index\" i WHERE Name = ?", "EmpDepartmentSalaryIndex").FirstOrDefault() == null)
    Db.SQL("CREATE INDEX EmpDepartmentSalaryIndex ON Employee (Department ASC, Salary DESC)");

Dropping Indexes

Existing indexes can be dropped from a database by query with syntax DROP INDEX index_name ON table_name. For example:

Db.SQL("DROP INDEX EmpDepartmentSalaryIndex ON Employee");

Recommendations

For all SELECT statements in your programming code, it is recommended to declare, when possible, indexes for:

  • all conditions in WHERE clauses,

  • all join conditions,

  • all sort specifications in ORDER BY clauses.

An execution of the query (11) below can make use of an index on the property/column FirstName such as the index (1) above. It can also make use of combined indexes such as (7) or (8) where the first property/column of the index is FirstName. It can not make use of the combined index (6) where FirstName is not the first property/column of the index.

An execution of the query (12), where we have two equality comparisons on FirstName and LastName, can make use of any of the combined indexes (6), (7) and (8), where the two first properties/columns of the indexes are FirstName and LastName.

An execution of the query (13) can efficiently make use of the combined indexes (7) and (8) because the first property/column of the index is FirstName, on which we have an equality comparison, and the second property/column of the index is LastName, on which we have a range comparison. However, an execution of this query can not efficiently make use of the combined index (6) because the range condition on the first property/column LastName of the index makes it not possible to use the equality condition on the subsequent property/column FirstName.

An execution of the join in the query (14) can make use of the indexes (5) or (9), since we need an index to efficiently find all Employee objects/rows for a particular Department object/row.

An execution of the query (15) can make use of the combined index (6) to find all Employee objects/rows in the requested order without any sorting.

An execution of the query (16) can also make use of the combined index (6) to find all Employee objects/rows in the requested order without any sorting, since the index can be traversed in the reverse order.

An execution of the query (17) can make use of the combined index (7) in the reverse order to find all Employees objects/rows in the requested order without any sorting order. However, an execution of this query can not efficienlty make use of the combined index (8) since it neither in the normal nor the reverse order match the requested order.

(11) SELECT e FROM Employee e WHERE e.FirstName = ?

(12) SELECT e FROM Employee e WHERE e.FirstName = ? AND e.LastName = ?

(13) SELECT e FROM Employee e WHERE e.FirstName = ? AND e.LastName > ?

(14) SELECT e, d FROM Employee e JOIN Department d
         ON e.Department = d WHERE d.Name = ?

(15) SELECT e FROM Employee e ORDER BY e.LastName ASC, e.FirstName ASC

(16) SELECT e FROM Employee e ORDER BY e.LastName DESC, e.FirstName DESC

(17) SELECT e FROM Employee e ORDER BY e.FirstName DESC, e.LastName DESC

Index Hints in Queries

Derived Indexes

The current version do not support derived indexes. You need to define index on the class you like to query. For instance, say we have the following structure:

[Database]
public class LegalEntity
{
   public string Name { get; set; }
}

public class Company : LegalEntity
{}

public class Person : LegalEntity
{}

You will need to define index on Name for both Company and Person.

If index is defined on a database property for the base class, the query optimizer might choose to use it in queries on a child class of the base class, but this will require to filter out all instances, which are not of the child class. For example, index is created on Name only for LegalEntity and a query is submitted for Company, then if the query optimizer chooses to use the index, it will add a filter predicate, which checks that all objects from the index are instances of Company.

PreviousOffset KeyNextLiterals

Last updated 7 years ago

You can give a hint to Starcounter on what index to use for a specific query. See for more information.

Hints