Allow creating index concurrently
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Allow creating indexes concurrently
|
||||
* Allow skipping index creation
|
||||
* Add assert methods to test tools
|
||||
* Set ELLIPSIS option flag on doctest
|
||||
|
||||
@@ -304,11 +304,14 @@ TableHandler
|
||||
Drop the named ``ident`` constraint.
|
||||
``table`` can be used to alter another table.
|
||||
|
||||
.. method:: TableHandler.set_indexes(indexes)
|
||||
.. method:: TableHandler.set_indexes(indexes[, concurrently])
|
||||
|
||||
Create the :class:`indexes <trytond.model.Index>` if possible and drop
|
||||
others having ``idx_`` as prefix or ``_index`` as suffix.
|
||||
|
||||
If ``concurrently`` is set indexes are created concurrently if possible.
|
||||
It defaults to ``False``.
|
||||
|
||||
.. method:: TableHandler.drop_column(column_name)
|
||||
|
||||
Drop the named column.
|
||||
|
||||
@@ -494,7 +494,7 @@ class TableHandler(TableHandlerInterface):
|
||||
Identifier(self.table_name), Identifier(ident)))
|
||||
self._update_definitions(constraints=True)
|
||||
|
||||
def set_indexes(self, indexes):
|
||||
def set_indexes(self, indexes, concurrently=False):
|
||||
cursor = Transaction().connection.cursor()
|
||||
old = set(self._indexes)
|
||||
for index in indexes:
|
||||
@@ -504,7 +504,18 @@ class TableHandler(TableHandlerInterface):
|
||||
name = '_'.join([self.table_name, name])
|
||||
name = 'idx_' + self.convert_name(name, reserved=len('idx_'))
|
||||
cursor.execute(
|
||||
SQL('CREATE INDEX IF NOT EXISTS {} ON {} USING {}').format(
|
||||
'SELECT idx.indisvalid '
|
||||
'FROM pg_index idx '
|
||||
'JOIN pg_class cls ON cls.oid = idx.indexrelid '
|
||||
'WHERE cls.relname = %s',
|
||||
(name,))
|
||||
if (idx_valid := cursor.fetchone()) and not idx_valid[0]:
|
||||
cursor.execute(
|
||||
SQL("DROP INDEX {}").format(Identifier(name)))
|
||||
cursor.execute(
|
||||
SQL('CREATE INDEX {} IF NOT EXISTS {} ON {} USING {}')
|
||||
.format(
|
||||
SQL('CONCURRENTLY' if concurrently else ''),
|
||||
Identifier(name),
|
||||
Identifier(self.table_name),
|
||||
query),
|
||||
|
||||
@@ -278,7 +278,7 @@ class TableHandler(TableHandlerInterface):
|
||||
def drop_constraint(self, ident, table=None):
|
||||
warnings.warn('Unable to drop constraint with SQLite backend')
|
||||
|
||||
def set_indexes(self, indexes):
|
||||
def set_indexes(self, indexes, concurrently=False):
|
||||
cursor = Transaction().connection.cursor()
|
||||
old = set(self._indexes)
|
||||
for index in indexes:
|
||||
|
||||
@@ -107,7 +107,7 @@ class TableHandlerInterface(object):
|
||||
name = hashlib.sha256(name).hexdigest()[:length - 1]
|
||||
return name
|
||||
|
||||
def set_indexes(self, indexes):
|
||||
def set_indexes(self, indexes, concurrently=False):
|
||||
raise NotImplementedError
|
||||
|
||||
def index_translator_for(self, index):
|
||||
|
||||
@@ -516,7 +516,7 @@ class ModelSQL(ModelStorage):
|
||||
[h_table.write_date], [None]))
|
||||
|
||||
@classmethod
|
||||
def _update_sql_indexes(cls):
|
||||
def _update_sql_indexes(cls, concurrently=False):
|
||||
def no_subset(index):
|
||||
for j in cls._sql_indexes:
|
||||
if j != index and index < j:
|
||||
@@ -525,11 +525,11 @@ class ModelSQL(ModelStorage):
|
||||
if not callable(cls.table_query):
|
||||
table_h = cls.__table_handler__()
|
||||
indexes = filter(no_subset, cls._sql_indexes)
|
||||
table_h.set_indexes(indexes)
|
||||
table_h.set_indexes(indexes, concurrently=concurrently)
|
||||
if cls._history:
|
||||
history_th = cls.__table_handler__(history=True)
|
||||
indexes = filter(no_subset, cls._history_sql_indexes)
|
||||
history_th.set_indexes(indexes)
|
||||
history_th.set_indexes(indexes, concurrently=concurrently)
|
||||
|
||||
@classmethod
|
||||
def _update_history_table(cls):
|
||||
|
||||
@@ -246,13 +246,16 @@ def load_module_graph(graph, pool, update=None, lang=None, indexes=True):
|
||||
|
||||
pool.setup_mixin()
|
||||
|
||||
def create_indexes(concurrently):
|
||||
for model_name in models_with_indexes:
|
||||
model = pool.get(model_name)
|
||||
if model._sql_indexes:
|
||||
logger.info('index:update %s', model_name)
|
||||
model._update_sql_indexes(concurrently=concurrently)
|
||||
|
||||
if update:
|
||||
if indexes:
|
||||
for model_name in models_with_indexes:
|
||||
model = pool.get(model_name)
|
||||
if model._sql_indexes:
|
||||
logger.info('index:create %s', model_name)
|
||||
model._update_sql_indexes()
|
||||
create_indexes(concurrently=False)
|
||||
transaction.commit()
|
||||
else:
|
||||
logger.info('index:skipping indexes creation')
|
||||
@@ -262,6 +265,9 @@ def load_module_graph(graph, pool, update=None, lang=None, indexes=True):
|
||||
logger.info('history:update %s', model.__name__)
|
||||
model._update_history_table()
|
||||
transaction.commit()
|
||||
elif indexes:
|
||||
with transaction.new_transaction(autocommit=True):
|
||||
create_indexes(concurrently=True)
|
||||
|
||||
# Vacuum :
|
||||
while modules_todo:
|
||||
|
||||
Reference in New Issue
Block a user