From 566ae798df12c9d187ffc4b5cc560ef509859977 Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Fri, 15 Jul 2016 11:34:59 +0100 Subject: [PATCH] Speed up GET services endpoints Add additional relationships to exclude in the ServiceSchema metaclass. Marshmallow by default lazily loads relationships when dumping, so any relationships we know we won't need, we can exclude and avoid a DB call. Lots of tables are linked to services, so it loads a lot of tables. So don't load statistics tables, since they're clearly not needed. We *do* however want to return the users for the service - they're used in a few places. If we're returning all services, then we don't want to make separate queries for these users, so we modify the services_dao queries to load users the first time round. This should speed up all GET queries to the services endpoints, most notably pages that get many services (platform_admin, choose service, login) --- app/dao/services_dao.py | 28 ++++++++++++++++++++++++---- app/schemas.py | 10 +++++++++- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/app/dao/services_dao.py b/app/dao/services_dao.py index e86bf74f6..d1bb8efbe 100644 --- a/app/dao/services_dao.py +++ b/app/dao/services_dao.py @@ -3,6 +3,7 @@ import uuid from app import db from app.models import Service from sqlalchemy import asc +from sqlalchemy.orm import joinedload from app.dao.dao_utils import ( transactional, @@ -27,19 +28,38 @@ from app.models import ( def dao_fetch_all_services(): - return Service.query.order_by(asc(Service.created_at)).all() + return Service.query.order_by( + asc(Service.created_at) + ).options( + joinedload('users') + ).all() def dao_fetch_service_by_id(service_id): - return Service.query.filter_by(id=service_id).one() + return Service.query.filter_by( + id=service_id + ).options( + joinedload('users') + ).one() def dao_fetch_all_services_by_user(user_id): - return Service.query.filter(Service.users.any(id=user_id)).order_by(asc(Service.created_at)).all() + return Service.query.filter( + Service.users.any(id=user_id) + ).order_by( + asc(Service.created_at) + ).options( + joinedload('users') + ).all() def dao_fetch_service_by_id_and_user(service_id, user_id): - return Service.query.filter(Service.users.any(id=user_id)).filter_by(id=service_id).one() + return Service.query.filter( + Service.users.any(id=user_id), + Service.id == service_id + ).options( + joinedload('users') + ).one() @transactional diff --git a/app/schemas.py b/app/schemas.py index b4ac775d9..eed567401 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -106,7 +106,15 @@ class ServiceSchema(BaseSchema): class Meta: model = models.Service - exclude = ("updated_at", "created_at", "api_keys", "templates", "jobs", 'old_id') + exclude = ('updated_at', + 'created_at', + 'api_keys', + 'templates', + 'jobs', + 'old_id', + 'template_statistics', + 'service_provider_stats', + 'service_notification_stats') strict = True @validates('sms_sender')