Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: re-add totals and limits #2631

Merged
merged 2 commits into from
Aug 17, 2023
Merged

Conversation

matthewelwell
Copy link
Contributor

Changes

Re-add totals and limits removed in #2625 due to performance issues.

Uses separate queries instead of annotate(Count(..., distinct=True)) to avoid further performance issues.

How did you test this code?

Updated the test from the previous iteration to ensure its verifying that the numbers are correct. I've been unable to really reproduce the performance issues we saw in production, but there is a lot less black magic going on with this approach. The additional queries should have a negligible impact on performance.

Add broken test to prove issue when not using distinct
@matthewelwell matthewelwell requested review from a team and novakzaballa August 10, 2023 15:49
@github-actions github-actions bot added the api Issue related to the REST API label Aug 10, 2023
@vercel
Copy link

vercel bot commented Aug 10, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 10, 2023 3:52pm
flagsmith-frontend-preview ✅ Ready (Inspect) Visit Preview Aug 10, 2023 3:52pm
flagsmith-frontend-staging ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 10, 2023 3:52pm

@github-actions
Copy link
Contributor

github-actions bot commented Aug 10, 2023

Uffizzi Preview deployment-33159 was deleted.

@codecov-commenter
Copy link

codecov-commenter commented Aug 10, 2023

Codecov Report

Patch coverage: 100.00% and no project coverage change.

Comparison is base (1514bf7) 95.44% compared to head (7010811) 95.44%.
Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2631   +/-   ##
=======================================
  Coverage   95.44%   95.44%           
=======================================
  Files         976      976           
  Lines       27319    27327    +8     
=======================================
+ Hits        26074    26082    +8     
  Misses       1245     1245           
Files Changed Coverage Δ
api/projects/views.py 94.16% <ø> (-0.15%) ⬇️
api/projects/serializers.py 100.00% <100.00%> (ø)
...pi/tests/unit/projects/test_unit_projects_views.py 100.00% <100.00%> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

return Environment.objects.all()
queryset = Environment.objects.all()

if self.action == "retrieve":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add the SQL generated by this and the results of the explain analyze (performed on the production database).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Limit  (cost=45.19..45.21 rows=1 width=724) (actual time=0.089..0.090 rows=1 loops=1)
  ->  GroupAggregate  (cost=45.19..45.21 rows=1 width=724) (actual time=0.088..0.089 rows=1 loops=1)
        Group Key: environments_environment.id, projects_project.id, organisations_organisation.id
        ->  Sort  (cost=45.19..45.19 rows=1 width=720) (actual time=0.084..0.085 rows=1 loops=1)
              Sort Key: environments_environment.id, projects_project.id, organisations_organisation.id
              Sort Method: quicksort  Memory: 25kB
              ->  Nested Loop  (cost=1.15..45.18 rows=1 width=720) (actual time=0.078..0.080 rows=1 loops=1)
                    ->  Nested Loop  (cost=0.86..44.81 rows=1 width=637) (actual time=0.064..0.065 rows=1 loops=1)
                          ->  Nested Loop Left Join  (cost=0.57..36.50 rows=1 width=555) (actual time=0.049..0.051 rows=1 loops=1)
                                ->  Index Scan using environments_environment_api_key_b1cbb73a_like on environments_environment  (cost=0.29..8.30 rows=1 width=551) (actual time=0.024..0.024 rows=1 loops=1)
                                      Index Cond: ((api_key)::text = 'c9qkLTj6BAgmxpUyPoZXYi'::text)
                                      Filter: (deleted_at IS NULL)
                                ->  Index Scan using features_featuresegment_environment_id_05e7007b on features_featuresegment  (cost=0.29..28.11 rows=9 width=8) (actual time=0.023..0.024 rows=1 loops=1)
                                      Index Cond: (environments_environment.id = environment_id)
                          ->  Index Scan using projects_project_pkey on projects_project  (cost=0.29..8.30 rows=1 width=82) (actual time=0.013..0.014 rows=1 loops=1)
                                Index Cond: (id = environments_environment.project_id)
                    ->  Index Scan using organisations_organisation_pkey on organisations_organisation  (cost=0.29..0.37 rows=1 width=83) (actual time=0.013..0.013 rows=1 loops=1)
                          Index Cond: (id = projects_project.organisation_id)
Planning Time: 0.998 ms
Execution Time: 0.187 ms

This one should be ok as we're not having to add any distinct keywords.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, here is the sql too:

select
	"environments_environment"."id",
	"environments_environment"."deleted_at",
	"environments_environment"."name",
	"environments_environment"."created_date",
	"environments_environment"."description",
	"environments_environment"."project_id",
	"environments_environment"."api_key",
	"environments_environment"."minimum_change_request_approvals",
	"environments_environment"."webhooks_enabled",
	"environments_environment"."webhook_url",
	"environments_environment"."allow_client_traits",
	"environments_environment"."updated_at",
	"environments_environment"."banner_text",
	"environments_environment"."banner_colour",
	"environments_environment"."hide_disabled_flags",
	"environments_environment"."use_mv_v2_evaluation",
	"environments_environment"."hide_sensitive_data",
	COUNT("features_featuresegment"."id") as "total_segment_overrides",
	"projects_project"."id",
	"projects_project"."deleted_at",
	"projects_project"."uuid",
	"projects_project"."name",
	"projects_project"."created_date",
	"projects_project"."organisation_id",
	"projects_project"."hide_disabled_flags",
	"projects_project"."enable_dynamo_db",
	"projects_project"."prevent_flag_defaults",
	"projects_project"."enable_realtime_updates",
	"projects_project"."only_allow_lower_case_feature_names",
	"projects_project"."feature_name_regex",
	"projects_project"."max_segments_allowed",
	"projects_project"."max_features_allowed",
	"projects_project"."max_segment_overrides_allowed",
	"organisations_organisation"."id",
	"organisations_organisation"."deleted_at",
	"organisations_organisation"."uuid",
	"organisations_organisation"."name",
	"organisations_organisation"."has_requested_features",
	"organisations_organisation"."webhook_notification_email",
	"organisations_organisation"."created_date",
	"organisations_organisation"."alerted_over_plan_limit",
	"organisations_organisation"."stop_serving_flags",
	"organisations_organisation"."restrict_project_create_to_admin",
	"organisations_organisation"."persist_trait_data",
	"organisations_organisation"."block_access_to_admin",
	"organisations_organisation"."feature_analytics"
from
	"environments_environment"
left outer join "features_featuresegment" on
	("environments_environment"."id" = "features_featuresegment"."environment_id")
inner join "projects_project" on
	("environments_environment"."project_id" = "projects_project"."id")
inner join "organisations_organisation" on
	("projects_project"."organisation_id" = "organisations_organisation"."id")
where
	("environments_environment"."deleted_at" is null
		and "environments_environment"."api_key" = '<key>')
group by
	"environments_environment"."id",
	"projects_project"."id",
	"organisations_organisation"."id"
limit 21

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Issue related to the REST API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants