diff --git a/conf/recordmanager.ini.sample b/conf/recordmanager.ini.sample index dede7d423..ba8b8b6f1 100644 --- a/conf/recordmanager.ini.sample +++ b/conf/recordmanager.ini.sample @@ -72,6 +72,9 @@ counts = false ;username = "recman" ; Password ;password = "topsecret" +; Whether to use index hints (MySQL/MariaDB). Recommended to keep enabled (default) +; unless trying to solve performance issues. +use_index_hints = true [Solr] ; Update URL. Note that RecordManager requires that the json update method be available. diff --git a/src/RecordManager/Base/Database/PDODatabase.php b/src/RecordManager/Base/Database/PDODatabase.php index 5c8b8ddfa..3c16b5e05 100644 --- a/src/RecordManager/Base/Database/PDODatabase.php +++ b/src/RecordManager/Base/Database/PDODatabase.php @@ -105,6 +105,13 @@ class PDODatabase extends AbstractDatabase */ protected $lastRecordAttrsId = []; + /** + * Whether to use index hints (MySQL/MariaDB) + * + * @var bool + */ + protected $useIndexHints = false; + /** * Constructor. * @@ -119,6 +126,7 @@ public function __construct(array $config) $this->dsn = $config['connection'] ?? ''; $this->username = $config['username'] ?? ''; $this->password = $config['password'] ?? ''; + $this->useIndexHints = (bool)($config['use_index_hints'] ?? true); } /** @@ -712,6 +720,9 @@ protected function findPDORecords( [$where, $params] = $this->filterToSQL($collection, $filter); [$fields, $sqlOptions] = $this->optionsToSQL($options); $sql = "select $fields from $collection"; + if ($hints = $this->getIndexHints($collection, $filter, $options)) { + $sql .= " $hints"; + } if ($where) { $sql .= " where $where"; } @@ -1224,4 +1235,35 @@ protected function getMainFields(string $collection): array } return $this->mainFields[$collection]; } + + /** + * Check if the database is MySQL or MariaDB + * + * @return bool + */ + protected function isMySQLCompatible(): bool + { + return str_starts_with($this->dsn, 'mysql') + || str_starts_with($this->dsn, 'mariadb'); + } + + /** + * Get index hints + * + * @param string $collection Collection + * @param array $filter Search filter + * @param array $options Options such as sorting + * + * @return string + */ + protected function getIndexHints(string $collection, array $filter, array $options): string + { + if (!$this->useIndexHints || !$this->isMySQLCompatible()) { + return ''; + } + if ('record' === $collection && isset($options['sort']['_id'])) { + return 'USE INDEX (source_update_needed)'; + } + return ''; + } }