citusdata / django-multitenant

Python/Django support for distributed multi-tenant databases like Postgres+Citus
MIT License
707 stars 116 forks source link

Redundant queries when using related managers #214

Open GuySharir opened 2 months ago

GuySharir commented 2 months ago

When trying to access objects through the related manager there are N extra queries that are performed that are unnecessary. The problem is at __setattr__, specifically at is_val_equal_to_tenant (code). The problen is that when we try to check the equality of val and self.tenant_object we perform another DB call to fetch the tenant.

reproduce:

from django_multitenant.tests.base import BaseTestCase
from django_multitenant.tests.models import Project

class RelatedMangerTestCase(BaseTestCase):
    def test(self):
        account = self.account_fr
        _proj_1 = Project.objects.create(name="project_1", account=account)
        _proj_2 = Project.objects.create(name="project_2", account=account)

        with self.assertNumQueries(1):
            # This will fail, the actual amount of queries is 3
            # 1 for the SELECT query to get the projects
            # and then 2 more queries to fetch the tenant 1 for each project
            list(account.projects.all())
First expected query ```sql SELECT "tests_project"."id", "tests_project"."name", "tests_project"."account_id", "tests_project"."employee_id" FROM "tests_project" WHERE "tests_project"."account_id" = 1 ```
Extra queries This query will be executed once for each related object (in this case 2 times) so when we have N related objects we will result in N extra queries. ```sql SELECT "tests_account"."id", "tests_account"."name", "tests_account"."domain", "tests_account"."subdomain", "tests_account"."country_id", "tests_account"."employee_id" FROM "tests_account" WHERE "tests_account"."id" = 1 LIMIT 21 ```