-
Notifications
You must be signed in to change notification settings - Fork 73
DOC Document default_sort composite indexes #755
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
emteknetnz
merged 1 commit into
silverstripe:6
from
creative-commoners:pulls/6/default-sort-index
Jun 5, 2025
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,7 +25,8 @@ The Silverstripe CMS framework already places certain indexes for you by default | |
| - The `ClassName` column if your model inherits from `DataObject` | ||
| - 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). | ||
| - All fields used in `default_sort` configuration | ||
| - All fields used in `default_sort` configuration (see [`default_sort` index mode](#default-sort-index-mode) below for additional options) | ||
| - Some built-in models (such as [`Member`](api:SilverStripe\Security\Member)) have specific indexes added | ||
|
|
||
| ## Defining an index | ||
|
|
||
|
|
@@ -39,7 +40,7 @@ use SilverStripe\ORM\DataObject; | |
|
|
||
| class MyObject extends DataObject | ||
| { | ||
| private static $indexes = [ | ||
| private static array $indexes = [ | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unrelated - just updating the config references in this page to follow latest best practice |
||
| '<column-name>' => true, | ||
| '<index-name>' => [ | ||
| 'type' => '<type>', | ||
|
|
@@ -74,12 +75,12 @@ use SilverStripe\ORM\DataObject; | |
|
|
||
| class MyTestObject extends DataObject | ||
| { | ||
| private static $db = [ | ||
| private static array $db = [ | ||
| 'MyField' => 'Varchar', | ||
| 'MyOtherField' => 'Varchar', | ||
| ]; | ||
|
|
||
| private static $indexes = [ | ||
| private static array $indexes = [ | ||
| 'MyIndexName' => ['MyField', 'MyOtherField'], | ||
| ]; | ||
| } | ||
|
|
@@ -90,21 +91,113 @@ class MyTestObject extends DataObject | |
| 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. | ||
|
|
||
| - index (col1) - `WHERE col1 = ?` | ||
| - index (col1, col2) = `WHERE (col1 = ? AND col2 = ?)` | ||
| - index (col1, col2, col3) = `WHERE (col1 = ? AND col2 = ? AND col3 = ?)` | ||
| ```php | ||
| namespace App\Model; | ||
|
|
||
| use SilverStripe\ORM\DataObject; | ||
|
|
||
| class MyTestObject extends DataObject | ||
| { | ||
| // ... | ||
| private static array $indexes = [ | ||
| 'MyCompositeIndex' => ['MyField', 'MyOtherField', 'MyThirdField'], | ||
| ]; | ||
| } | ||
| ``` | ||
|
|
||
| Composite indexes can be used for any query that uses the fields in this specific order, include queries that omit columns from later in the index. For example, the index would be used for these queries: | ||
|
|
||
| The index would not be used for a query `WHERE col2 = ?` or for `WHERE col1 = ? OR col2 = ?` | ||
| - `WHERE MyField = ?` | ||
| - `WHERE (MyField = ? AND MyOtherField = ?)` | ||
| - `WHERE (MyField = ? AND MyOtherField = ? AND MyThirdField = ?)` | ||
|
|
||
| The index would not be used for a query `WHERE MyOtherField = ?` (because the first column is not used in this query) or for `WHERE MyField = ? OR MyOtherField = ?` (because the database has to check all rows to see if the `MyOtherField` column matches on its own). | ||
|
|
||
| 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. | ||
|
|
||
| ### Directionality | ||
|
|
||
| You can choose to define the direction for each column in the index. This can be useful if you know you usually sort a model in a specific direction. It's crucial for composite indexes if you are sorting on one column in a different direction than the others. | ||
|
|
||
| The direction is defined by adding either `ASC` or `DESC` after the column name. `ASC` is implied if no direction is specified. | ||
|
|
||
| ```php | ||
| namespace App\Model; | ||
|
|
||
| use SilverStripe\ORM\DataObject; | ||
|
|
||
| class MyTestObject extends DataObject | ||
| { | ||
| // ... | ||
| private static array $indexes = [ | ||
| 'MyCompositeIndex' => ['MyField ASC', 'MyOtherField DESC'], | ||
| ]; | ||
| } | ||
| ``` | ||
|
|
||
| ### `default_sort` index mode {#default-sort-index-mode} | ||
|
|
||
| By default, if the [`default_sort`](api:SilverStripe\ORM\DataObject->default_sort) configuration for your `DataObject` subclass specifies multiple columns, the ORM will create an index for each column as well as a composite index that includes all of the columns in your sort order. The composite index is always called `default_sort_composite`. | ||
|
|
||
| You can change what indexes will be created by setting the [`default_sort_index_mode`](api:SilverStripe\ORM\DataObject->default_sort_index_mode) configuration for your class. It takes the following options: | ||
|
|
||
| |Constant|Value|What it does| | ||
| |---|---|---| | ||
| |[`DataObjectSchema::SORT_INDEX_MODE_NONE`](api:SilverStripe\ORM\DataObjectSchema::SORT_INDEX_MODE_NONE)|none|Do not create any indexes for `default_sort`. Implies you will define your own indexes.| | ||
| |[`DataObjectSchema::SORT_INDEX_MODE_SINGLE`](api:SilverStripe\ORM\DataObjectSchema::SORT_INDEX_MODE_SINGLE)|single|Do not create a composite index, only create an index for each column.| | ||
| |[`DataObjectSchema::SORT_INDEX_MODE_COMPOSITE`](api:SilverStripe\ORM\DataObjectSchema::SORT_INDEX_MODE_COMPOSITE)|composite|Create only a composite index, not an index for each column.| | ||
| |[`DataObjectSchema::SORT_INDEX_MODE_BOTH`](api:SilverStripe\ORM\DataObjectSchema::SORT_INDEX_MODE_BOTH)|both|Create both a composite index and an index for each column (this is the default).| | ||
|
|
||
| > [!WARNING] | ||
| > Note that the ORM cannot create composite indexes that include columns in a different table (e.g. from a parent class or a relation). | ||
|
|
||
| If you have the following classes: | ||
|
|
||
| ```php | ||
| namespace App\Model; | ||
|
|
||
| use SilverStripe\ORM\DataObject; | ||
|
|
||
| class MyTestObject extends DataObject | ||
| { | ||
| private static array $db = [ | ||
| 'MyField' => 'Varchar', | ||
| 'MyOtherField' => 'Varchar', | ||
| ]; | ||
|
|
||
| private static array $default_sort = 'ID'; | ||
| } | ||
| ``` | ||
|
|
||
| ```php | ||
| namespace App\Model; | ||
|
|
||
| class MySubclass extends MyTestObject | ||
| { | ||
| private static array $db = [ | ||
| 'MyThirdField' => 'Varchar', | ||
| ]; | ||
|
|
||
| private static array $default_sort = 'MyField, MyOtherField, MyThirdField'; | ||
| } | ||
| ``` | ||
|
|
||
| The ORM will not create a composite index for either class. It doesn't create one for `MyTestObject` because its `default_sort` definition only includes one column, and it doesn't create one for `MySubclass` because the first two columns it references belong on the superclass table, not the subclass table. | ||
|
|
||
| > [!NOTE] | ||
| > If you set `default_sort_index_mode` to "Composite" but your `default_sort` configuration only contains a single column, a `default_sort_composite` index will be created, though it will only contain that single column. | ||
|
|
||
| In these situations you may want to create your own composite index - for this example it would be an index with the first two columns in the `MyTestObject` table, as it is likely this index would be used when sorting `MySubclass` records. | ||
|
|
||
| Note that `ID` as a column at the *end* of your sort order won't be included in any composite indexes, because the database already implicitly adds that to all indexes. | ||
|
|
||
| ## Index creation/destruction | ||
|
|
||
| Indexes are generated and removed automatically when building the database based on your configuration. Caution if you're working with large tables and | ||
| modify an index as the next time the database is built it will `DROP` the index, and then `ADD` it. | ||
|
|
||
| Note that the ORM won't automatically drop indexes if you remove them from the `indexes` configuration array. Instead, you need to set the value to `false` like so: | ||
| Note that the ORM won't automatically drop indexes if you remove them from the `indexes` configuration array or update your `default_sort` configuration. Instead, you need to set the value to `false` like so: | ||
|
|
||
| ```php | ||
| namespace App\Model; | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this last note for completion's sake