NEW Allow InnoDB for FULLTEXT indexes

MyISAM used to be the only one to support it, now InnoDB has caught up.
Unless an engine is set specifically in create_table_options,
this will auto-convert existing MyISAM tables to InnoDb.

Fixes #9242
This commit is contained in:
Ingo Schommer 2020-04-07 08:26:11 +12:00
parent f1c74c3570
commit c6b698cb02
5 changed files with 61 additions and 40 deletions

View File

@ -0,0 +1,55 @@
# 4.6.0 (Unreleased)
## Overview {#overview}
* [MySQL tables are auto-converted from MyISAM to InnoDB](#myisam)
## MySQL tables are auto-converted from MyISAM to InnoDB {#myisam}
Beginning with [4.4.0](https://docs.silverstripe.org/en/4/changelogs/4.4.0/),
our minimum requirement for MySQL is 5.6 (since MySQL 5.5 end of life reached in December 2018).
Starting with MySQL 5.6, [InnoDB](https://dev.mysql.com/doc/refman/5.6/en/innodb-introduction.html)
is the new default storage engine,
replacing the older [MyISAM](https://dev.mysql.com/doc/refman/5.6/en/myisam-storage-engine.html) engine.
Silverstripe CMS already creates InnoDB tables by default,
mainly in order to benefit from their better support for database transactions.
Before MySQL 5.6, InnoDB didn't have a `FULLTEXT` search index,
requiring us to enforce the MyISAM engine when devs opted into this index type
in their particular setup. There are a few ways in which this opt-in can happen:
* Adding the [FulltextSearchable](https://github.com/silverstripe/silverstripe-framework/blob/4/src/ORM/Search/FulltextSearchable.php)
extension to a DataObject, as described in our
[search docs](https://docs.silverstripe.org/en/4/developer_guides/search/fulltextsearch/)
* Defining `'type' => 'fulltext'` in `DataObject::$db` column definitions
* Implementing [DBIndexable](https://github.com/silverstripe/silverstripe-framework/blob/4/src/ORM/FieldType/DBIndexable.php)
on a custom `DBField` subclass.
* Setting `'ENGINE=MyISAM'` in `DataObject::$create_table_options`
This search index is not required to enable simple text search
in the "Pages" section of the CMS, or any ModelAdmin implementations.
We generally recommend to choose a more powerful
[search addon](https://addons.silverstripe.org/add-ons?search=fulltext&type=&sort=downloads)
(e.g. based on Solr or ElasticSearch) for website frontend search use cases.
As of 4.6.0, a `dev/build` will automatically switch MyISAM tables to InnoDB,
which automatically recreates any indexes required. If you have large indexes,
this can extend the duration if this task. As usual, back up your database
before upgrading, and test upgrades on non-production systems first.
Our tests indicate that indexes with thousands of records and screen pages
worth of content (15MB index size) are converted in a few seconds.
In order to opt out of this change, you can set the engine explicitly
for your DataObject implementations:
```php
use SilverStripe\ORM\Connect\MySQLSchemaManager;
use SilverStripe\ORM\DataObject;
class MyDataObject extends DataObject
{
private static $create_table_options = [
MySQLSchemaManager::ID => 'ENGINE=MyISAM'
];
}
```

View File

@ -40,10 +40,6 @@ class MySQLSchemaManager extends DBSchemaManager
} }
if ($indexes) { if ($indexes) {
foreach ($indexes as $k => $v) { foreach ($indexes as $k => $v) {
// force MyISAM if we have a fulltext index
if ($v['type'] === 'fulltext') {
$addOptions = 'ENGINE=MyISAM';
}
$indexSchemas .= $this->getIndexSqlDefinition($k, $v) . ",\n"; $indexSchemas .= $this->getIndexSqlDefinition($k, $v) . ",\n";
} }
} }
@ -104,31 +100,12 @@ class MySQLSchemaManager extends DBSchemaManager
$dbID = self::ID; $dbID = self::ID;
if ($alteredOptions && isset($alteredOptions[$dbID])) { if ($alteredOptions && isset($alteredOptions[$dbID])) {
$indexList = $this->indexList($tableName);
$skip = false;
foreach ($indexList as $index) {
if ($index['type'] === 'fulltext') {
$skip = true;
break;
}
}
if ($skip) {
$this->alterationMessage(
sprintf(
"Table %s options not changed to %s due to fulltextsearch index",
$tableName,
$alteredOptions[$dbID]
),
"changed"
);
} else {
$this->query(sprintf("ALTER TABLE \"%s\" %s", $tableName, $alteredOptions[$dbID])); $this->query(sprintf("ALTER TABLE \"%s\" %s", $tableName, $alteredOptions[$dbID]));
$this->alterationMessage( $this->alterationMessage(
sprintf("Table %s options changed: %s", $tableName, $alteredOptions[$dbID]), sprintf("Table %s options changed: %s", $tableName, $alteredOptions[$dbID]),
"changed" "changed"
); );
} }
}
$alterations = implode(",\n", $alterList); $alterations = implode(",\n", $alterList);
$this->query("ALTER TABLE \"$tableName\" $alterations"); $this->query("ALTER TABLE \"$tableName\" $alterations");

View File

@ -2,7 +2,6 @@
namespace SilverStripe\ORM\Filters; namespace SilverStripe\ORM\Filters;
use SilverStripe\Core\Convert;
use SilverStripe\ORM\DataQuery; use SilverStripe\ORM\DataQuery;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
use Exception; use Exception;
@ -10,8 +9,7 @@ use Exception;
/** /**
* Filters by full-text matching on the given field. * Filters by full-text matching on the given field.
* *
* Full-text indexes are only available with MyISAM tables. The following column types are * The following column types are supported:
* supported:
* - Char * - Char
* - Varchar * - Varchar
* - Text * - Text

View File

@ -25,12 +25,6 @@ class DataObjectSchemaGenerationTest extends SapphireTest
// Start tests // Start tests
static::start(); static::start();
// enable fulltext option on this table
TestIndexObject::config()->update(
'create_table_options',
array(MySQLSchemaManager::ID => 'ENGINE=MyISAM')
);
parent::setUpBeforeClass(); parent::setUpBeforeClass();
} }

View File

@ -35,7 +35,4 @@ class TestObject extends DataObject implements TestOnly
], ],
); );
private static $create_table_options = array(
MySQLSchemaManager::ID => "ENGINE=MyISAM",
);
} }