2014-10-27 04:40:02 +01:00
|
|
|
title: Indexes
|
|
|
|
summary: Add Indexes to your Data Model to optimize database queries.
|
|
|
|
|
|
|
|
# Indexes
|
2017-04-07 01:27:07 +02:00
|
|
|
Indexes are a great way to improve performance in your application, especially as it grows. By adding indexes to your
|
|
|
|
data model you can reduce the time taken for the framework to find and filter data objects.
|
2014-10-27 04:40:02 +01:00
|
|
|
|
2017-04-07 01:27:07 +02:00
|
|
|
The addition of an indexes should be carefully evaluated as they can also increase the cost of other operations such as
|
2017-04-10 05:42:17 +02:00
|
|
|
`UPDATE`/`INSERT` and `DELETE`. An index on a column whose data is non unique will actually cost you performance.
|
|
|
|
E.g. In most cases an index on `boolean` status flag, or `ENUM` state will not increase query performance.
|
2017-04-07 01:27:07 +02:00
|
|
|
|
|
|
|
It's important to find the right balance to achieve fast queries using the optimal set of indexes; For SilverStripe
|
|
|
|
applications it's a good practice to:
|
|
|
|
- add indexes on columns which are frequently used in `filter`, `where` or `orderBy` statements
|
|
|
|
- for these, only include indexes for columns which are the most restrictive (return the least number of rows)
|
|
|
|
|
|
|
|
The SilverStripe framework already places certain indexes for you by default:
|
|
|
|
- The primary key for each model has a `PRIMARY KEY` unique index
|
2017-04-10 05:42:17 +02:00
|
|
|
- The `ClassName` column if your model inherits from `DataObject`
|
2017-04-07 01:27:07 +02:00
|
|
|
- All relationships defined in the model have indexes for their `has_one` entity (for `many_many` relationships
|
|
|
|
this index is present on the associative entity).
|
|
|
|
|
|
|
|
## Defining an index
|
2017-04-10 05:42:17 +02:00
|
|
|
Indexes are represented on a `DataObject` through the `DataObject::$indexes` array which maps index names to a
|
2017-04-07 01:27:07 +02:00
|
|
|
descriptor. There are several supported notations:
|
2014-10-27 04:40:02 +01:00
|
|
|
|
|
|
|
:::php
|
|
|
|
<?php
|
|
|
|
|
|
|
|
class MyObject extends DataObject {
|
|
|
|
|
2017-05-19 20:32:32 +02:00
|
|
|
private static $indexes = [
|
2014-10-27 04:40:02 +01:00
|
|
|
'<column-name>' => true,
|
2017-05-19 20:32:32 +02:00
|
|
|
'<index-name>' => [
|
2017-04-07 01:27:07 +02:00
|
|
|
'type' => '<type>',
|
2017-05-19 20:32:32 +02:00
|
|
|
'columns' => ['<column-name>', '<other-column-name>'],
|
|
|
|
],
|
|
|
|
'<index-name>' => ['<column-name>', '<other-column-name>'],
|
|
|
|
];
|
2014-10-27 04:40:02 +01:00
|
|
|
}
|
2017-04-07 01:27:07 +02:00
|
|
|
|
|
|
|
The `<column-name>` is used to put a standard non-unique index on the column specified. For complex or large tables
|
|
|
|
we recommend building the index to suite the requirements of your data.
|
2017-04-10 05:42:17 +02:00
|
|
|
|
2015-03-11 04:20:45 +01:00
|
|
|
The `<index-name>` can be an arbitrary identifier in order to allow for more than one index on a specific database
|
2014-10-27 04:40:02 +01:00
|
|
|
column. The "advanced" notation supports more `<type>` notations. These vary between database drivers, but all of them
|
|
|
|
support the following:
|
|
|
|
|
2017-04-07 01:27:07 +02:00
|
|
|
* `index`: Standard non unique index.
|
2014-10-27 04:40:02 +01:00
|
|
|
* `unique`: Index plus uniqueness constraint on the value
|
|
|
|
* `fulltext`: Fulltext content index
|
|
|
|
|
|
|
|
**mysite/code/MyTestObject.php**
|
|
|
|
|
|
|
|
:::php
|
|
|
|
<?php
|
|
|
|
|
|
|
|
class MyTestObject extends DataObject {
|
|
|
|
|
2017-05-19 20:32:32 +02:00
|
|
|
private static $db = [
|
2014-10-27 04:40:02 +01:00
|
|
|
'MyField' => 'Varchar',
|
|
|
|
'MyOtherField' => 'Varchar',
|
2017-05-19 20:32:32 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
private static $indexes = [
|
|
|
|
'MyIndexName' => ['MyField', 'MyOtherField'],
|
|
|
|
];
|
2014-10-27 04:40:02 +01:00
|
|
|
}
|
|
|
|
|
2017-04-07 01:27:07 +02:00
|
|
|
## Complex/Composite Indexes
|
|
|
|
For complex queries it may be necessary to define a complex or composite index on the supporting object. To create a
|
|
|
|
composite index, define the fields in the index order as a comma separated list.
|
|
|
|
|
2017-04-10 05:42:17 +02:00
|
|
|
*Note* Most databases only use the leftmost prefix to optimise the query, try to ensure the order of the index and your
|
2017-04-07 01:27:07 +02:00
|
|
|
query parameters are the same. e.g.
|
|
|
|
- index (col1) - `WHERE col1 = ?`
|
|
|
|
- index (col1, col2) = `WHERE (col1 = ? AND col2 = ?)`
|
|
|
|
- index (col1, col2, col3) = `WHERE (col1 = ? AND col2 = ? AND col3 = ?)`
|
|
|
|
|
|
|
|
The index would not be used for a query `WHERE col2 = ?` or for `WHERE col1 = ? OR col2 = ?`
|
|
|
|
|
|
|
|
As an alternative to a composite index, you can also create a hashed column which is a combination of information from
|
|
|
|
other columns. If this is indexed, smaller and reasonably unique it might be faster that an index on the whole column.
|
|
|
|
|
|
|
|
## Index Creation/Destruction
|
|
|
|
Indexes are generated and removed automatically during a `dev/build`. Caution if you're working with large tables and
|
|
|
|
modify an index as the next `dev/build` will `DROP` the index, and then `ADD` it.
|
|
|
|
|
2014-10-27 04:40:02 +01:00
|
|
|
## API Documentation
|
|
|
|
|
2015-03-11 04:20:45 +01:00
|
|
|
* [api:DataObject]
|