Opened 5 weeks ago

Last modified 8 days ago

#36143 assigned Cleanup/optimization

DatabaseOperations.bulk_batch_size() is overly protective on SQLite in most cases — at Version 1

Reported by: Sarah Boyce Owned by:
Component: Database layer (models, ORM) Version: 5.1
Severity: Normal Keywords:
Cc: Simon Charette Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no
Pull Requests:How to create a pull request

Description (last modified by Sarah Boyce)

DatabaseOperations.bulk_batch_size() for SQLite is dependent on DatabaseFeatures.max_query_params which is currently set as 999.

However, for SQLite versions >= 3.32, this limit is increased to 32,766. See: https://www.sqlite.org/limits.html#max_variable_number

SQLITE_MAX_VARIABLE_NUMBER, which defaults to 999 for SQLite versions prior to 3.32.0 (2020-05-22) or 32766 for SQLite versions after 3.32.0.

This means that is some cases (assuming there isn't another database limit being hit), we can increase the maximum batch size for SQLite.

For illustration purposes, on SQLite >= 3.32, if the value of DatabaseFeatures.max_query_params is increased, the following test would pass:

  • TabularUnified tests/bulk_create/tests.py

    diff --git a/tests/bulk_create/tests.py b/tests/bulk_create/tests.py
    index 7b86a2def5..ce9123ce97 100644
    a b class BulkCreateTests(TestCase):  
    286286        objs = [Country(name=f"Country {i}") for i in range(1000)]
    287287        fields = ["name", "iso_two_letter", "description"]
    288288        max_batch_size = max(connection.ops.bulk_batch_size(fields, objs), 1)
    289         with self.assertNumQueries(ceil(len(objs) / max_batch_size)):
     289        with self.assertNumQueries(1):
    290290            Country.objects.bulk_create(objs, batch_size=max_batch_size + 1)
    291291
    292292    @skipUnlessDBFeature("has_bulk_insert")

PR discussion references:

Ticket which sparked the discussion/discovery: #36118

According to the ticket's flags, the next step(s) to move this issue forward are:

  • To provide a patch by sending a pull request. Claim the ticket when you start working so that someone else doesn't duplicate effort. Before sending a pull request, review your work against the patch review checklist. Check the "Has patch" flag on the ticket after sending a pull request and include a link to the pull request in the ticket comment when making that update. The usual format is: [https://github.com/django/django/pull/#### PR].

Change History (1)

comment:1 by Sarah Boyce, 5 weeks ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top