Ver código fonte

Fixed #31275 -- Optimized sql_flush() without resetting sequences on MySQL.

Co-Authored-By: Simon Charette <charettes@users.noreply.github.com>
c-bata 5 anos atrás
pai
commit
89032876f4
3 arquivos alterados com 44 adições e 14 exclusões
  1. 1 0
      AUTHORS
  2. 33 14
      django/db/backends/mysql/operations.py
  3. 10 0
      docs/releases/3.1.txt

+ 1 - 0
AUTHORS

@@ -585,6 +585,7 @@ answer newbie questions, and generally made Django that much better:
     Martin von Gagern <gagern@google.com>
     Mart Sõmermaa <http://mrts.pri.ee/>
     Marty Alchin <gulopine@gamemusic.org>
+    Masashi Shibata <m.shibata1020@gmail.com>
     masonsimon+django@gmail.com
     Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
     Massimo Scamarcia <massimo.scamarcia@gmail.com>

+ 33 - 14
django/db/backends/mysql/operations.py

@@ -194,21 +194,40 @@ class DatabaseOperations(BaseDatabaseOperations):
         return 'RETURNING %s' % ', '.join(columns), ()
 
     def sql_flush(self, style, tables, sequences, allow_cascade=False):
-        # NB: The generated SQL below is specific to MySQL
-        # 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements
-        # to clear all tables of all data
-        if tables:
-            sql = ['SET FOREIGN_KEY_CHECKS = 0;']
-            for table in tables:
-                sql.append('%s %s;' % (
-                    style.SQL_KEYWORD('TRUNCATE'),
-                    style.SQL_FIELD(self.quote_name(table)),
-                ))
-            sql.append('SET FOREIGN_KEY_CHECKS = 1;')
-            sql.extend(self.sequence_reset_by_name_sql(style, sequences))
-            return sql
-        else:
+        if not tables:
             return []
+        sql = ['SET FOREIGN_KEY_CHECKS = 0;']
+        tables = set(tables)
+        with_sequences = set(s['table'] for s in sequences)
+        # It's faster to TRUNCATE tables that require a sequence reset since
+        # ALTER TABLE AUTO_INCREMENT is slower than TRUNCATE.
+        sql.extend(
+            '%s %s;' % (
+                style.SQL_KEYWORD('TRUNCATE'),
+                style.SQL_FIELD(self.quote_name(table_name)),
+            ) for table_name in tables.intersection(with_sequences)
+        )
+        # Otherwise issue a simple DELETE since it's faster than TRUNCATE
+        # and preserves sequences.
+        sql.extend(
+            '%s %s %s;' % (
+                style.SQL_KEYWORD('DELETE'),
+                style.SQL_KEYWORD('FROM'),
+                style.SQL_FIELD(self.quote_name(table_name)),
+            ) for table_name in tables.difference(with_sequences)
+        )
+        sql.append('SET FOREIGN_KEY_CHECKS = 1;')
+        return sql
+
+    def sequence_reset_by_name_sql(self, style, sequences):
+        return [
+            '%s %s %s %s = 1;' % (
+                style.SQL_KEYWORD('ALTER'),
+                style.SQL_KEYWORD('TABLE'),
+                style.SQL_FIELD(self.quote_name(sequence_info['table'])),
+                style.SQL_FIELD('AUTO_INCREMENT'),
+            ) for sequence_info in sequences
+        ]
 
     def validate_autopk_value(self, value):
         # MySQLism: zero in AUTO_INCREMENT field does not work. Refs #17653.

+ 10 - 0
docs/releases/3.1.txt

@@ -347,6 +347,10 @@ Models
 * :meth:`.QuerySet.bulk_create` now sets the primary key on objects when using
   MariaDB 10.5+.
 
+* The ``DatabaseOperations.sql_flush()`` method now generates more efficient
+  SQL on MySQL by using ``DELETE`` instead of ``TRUNCATE`` statements for
+  tables which don't require resetting sequences.
+
 Pagination
 ~~~~~~~~~~
 
@@ -415,6 +419,12 @@ Tests
 * :class:`~django.test.runner.DiscoverRunner` now skips running the system
   checks on databases not :ref:`referenced by tests<testing-multi-db>`.
 
+* :class:`~django.test.TransactionTestCase` teardown is now faster on MySQL
+  due to :djadmin:`flush` command improvements. As a side effect the latter
+  doesn't automatically reset sequences on teardown anymore. Enable
+  :attr:`.TransactionTestCase.reset_sequences` if your tests require this
+  feature.
+
 URLs
 ~~~~