Skip to content

Commit 04c1e6c

Browse files
Merge pull request #297 from eclecticiq/get-objects-performance-optimization
Get objects performance optimization
2 parents 6d3f1e1 + 0be5542 commit 04c1e6c

File tree

2 files changed

+31
-45
lines changed

2 files changed

+31
-45
lines changed

opentaxii/persistence/sqldb/api.py

Lines changed: 28 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
from typing import Dict, List, Optional, Tuple, no_type_check
77

88
import six
9+
import sqlalchemy
910
import structlog
1011
from sqlalchemy import and_, func, literal, or_
11-
from sqlalchemy.orm import Query, load_only
12+
from sqlalchemy.orm import Query, aliased, load_only
1213

1314
from opentaxii.common.sqldb import BaseSQLDatabaseAPI
1415
from opentaxii.persistence import OpenTAXII2PersistenceAPI, OpenTAXIIPersistenceAPI
@@ -801,61 +802,44 @@ def _apply_match_version(
801802
if "all" in match_version:
802803
return query
803804
version_filters = []
805+
804806
for value in match_version:
805807
if value == "first":
808+
VersionSTIXObject = aliased(taxii2models.STIXObject, name="oso_min")
809+
806810
min_versions_subq = (
807-
self.db.session.query(
808-
taxii2models.STIXObject.id,
809-
func.min(taxii2models.STIXObject.version).label("min_version"),
811+
sqlalchemy.select(
812+
func.min(VersionSTIXObject.version).label("min_version"),
810813
)
811-
.filter(
812-
taxii2models.STIXObject.collection_id == collection_id,
814+
.where( # type: ignore[call-arg]
815+
VersionSTIXObject.collection_id == collection_id,
816+
VersionSTIXObject.id == taxii2models.STIXObject.id,
813817
)
814-
.group_by(taxii2models.STIXObject.id)
815-
.subquery()
818+
.group_by(VersionSTIXObject.id)
819+
.scalar_subquery() # type: ignore[attr-defined]
820+
.correlate(taxii2models.STIXObject)
816821
)
817-
min_version_pks = (
818-
self.db.session.query(taxii2models.STIXObject.pk)
819-
.select_from(taxii2models.STIXObject)
820-
.join(
821-
min_versions_subq,
822-
(
823-
(taxii2models.STIXObject.id == min_versions_subq.c.id)
824-
& (
825-
taxii2models.STIXObject.version
826-
== min_versions_subq.c.min_version
827-
)
828-
),
829-
)
822+
version_filters.append(
823+
min_versions_subq == taxii2models.STIXObject.version
830824
)
831-
version_filters.append(taxii2models.STIXObject.pk.in_(min_version_pks))
832825
elif value == "last":
826+
VersionSTIXObject = aliased(taxii2models.STIXObject, name="oso_max")
827+
833828
max_versions_subq = (
834-
self.db.session.query(
835-
taxii2models.STIXObject.id,
836-
func.max(taxii2models.STIXObject.version).label("max_version"),
829+
sqlalchemy.select(
830+
func.max(VersionSTIXObject.version).label("max_version")
837831
)
838-
.filter(
839-
taxii2models.STIXObject.collection_id == collection_id,
832+
.where( # type: ignore[call-arg]
833+
VersionSTIXObject.collection_id == collection_id,
834+
VersionSTIXObject.id == taxii2models.STIXObject.id,
840835
)
841-
.group_by(taxii2models.STIXObject.id)
842-
.subquery()
836+
.group_by(VersionSTIXObject.id)
837+
.scalar_subquery() # type: ignore[attr-defined]
838+
.correlate(taxii2models.STIXObject)
843839
)
844-
max_version_pks = (
845-
self.db.session.query(taxii2models.STIXObject.pk)
846-
.select_from(taxii2models.STIXObject)
847-
.join(
848-
max_versions_subq,
849-
(
850-
(taxii2models.STIXObject.id == max_versions_subq.c.id)
851-
& (
852-
taxii2models.STIXObject.version
853-
== max_versions_subq.c.max_version
854-
)
855-
),
856-
)
840+
version_filters.append(
841+
max_versions_subq == taxii2models.STIXObject.version
857842
)
858-
version_filters.append(taxii2models.STIXObject.pk.in_(max_version_pks))
859843
else:
860844
version_filters.append(taxii2models.STIXObject.version == value)
861845
query = query.filter(reduce(or_, version_filters))
@@ -874,7 +858,7 @@ def _apply_limit(
874858
self, query: Query, limit: Optional[int] = None
875859
) -> Tuple[Query, bool]:
876860
if limit is not None:
877-
more = limit < query.count()
861+
more = limit < query.limit(limit + 1).count()
878862
query = query.limit(limit)
879863
else:
880864
more = False

opentaxii/persistence/sqldb/taxii2models.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,9 @@ class STIXObject(Base):
163163

164164
__table_args__ = (
165165
sqlalchemy.UniqueConstraint(collection_id, id, version),
166-
sqlalchemy.Index("ix_opentaxii_stixobject_date_added_id", date_added, id),
166+
sqlalchemy.Index(
167+
"ix_opentaxii_stixobject_col_date_added_id", collection_id, date_added, id
168+
),
167169
)
168170

169171
@classmethod

0 commit comments

Comments
 (0)