Skip to content

Commit

Permalink
perf: Refactor Dashboard.datasets_trimmed_for_slices (#15648)
Browse files Browse the repository at this point in the history
Co-authored-by: John Bodley <john.bodley@airbnb.com>
  • Loading branch information
john-bodley and John Bodley authored Jul 14, 2021
1 parent 42a1061 commit b3e699b
Showing 1 changed file with 37 additions and 10 deletions.
47 changes: 37 additions & 10 deletions superset/models/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@

import json
import logging
from collections import defaultdict
from functools import partial
from typing import Any, Callable, Dict, List, Set, Union
from typing import Any, Callable, Dict, List, Set, Tuple, Type, Union

import sqlalchemy as sqla
from flask_appbuilder import Model
Expand Down Expand Up @@ -171,8 +172,21 @@ def url(self) -> str:

@property
def datasources(self) -> Set[BaseDatasource]:
# pylint: disable=using-constant-test
return {slc.datasource for slc in self.slices if slc.datasource}
# Verbose but efficient database enumeration of dashboard datasources.
datasources_by_cls_model: Dict[Type["BaseDatasource"], Set[int]] = defaultdict(
set
)

for slc in self.slices:
datasources_by_cls_model[slc.cls_model].add(slc.datasource_id)

return {
datasource
for cls_model, datasource_ids in datasources_by_cls_model.items()
for datasource in db.session.query(cls_model)
.filter(cls_model.id.in_(datasource_ids))
.all()
}

@property
def charts(self) -> List[BaseDatasource]:
Expand Down Expand Up @@ -246,13 +260,26 @@ def data(self) -> Dict[str, Any]:
unless=lambda: not is_feature_enabled("DASHBOARD_CACHE"),
)
def datasets_trimmed_for_slices(self) -> List[Dict[str, Any]]:
datasource_slices = utils.indexed(self.slices, "datasource")
return [
# Filter out unneeded fields from the datasource payload
datasource.data_for_slices(slices)
for datasource, slices in datasource_slices.items()
if datasource
]
# Verbose but efficient database enumeration of dashboard datasources.
slices_by_datasource: Dict[
Tuple[Type["BaseDatasource"], int], Set[Slice]
] = defaultdict(set)

for slc in self.slices:
slices_by_datasource[(slc.cls_model, slc.datasource_id)].add(slc)

result: List[Dict[str, Any]] = []

for (cls_model, datasource_id), slices in slices_by_datasource.items():
datasource = (
db.session.query(cls_model).filter_by(id=datasource_id).one_or_none()
)

if datasource:
# Filter out unneeded fields from the datasource payload
result.append(datasource.data_for_slices(slices))

return result

@property # type: ignore
def params(self) -> str: # type: ignore
Expand Down

0 comments on commit b3e699b

Please sign in to comment.