avoid generate temporary table when query samples
Currently, when we call query-samples API, for SQL backend, we do
an inner join to get a temporary table, then apply filters, orderby
and limit options on it. Such implementation will drain disk space
or cause timeout exception when data set is growing, even with specified
limit and filters.
This patch applies filters and limit on the inner join itself, and
uses a fake mapper object instead of temporary table to suit current
query transformer.
Change-Id: I261a2dd362ed51c16a6fa191dadcce1b45fce2e4
Closes-Bug: #1506738
(cherry picked from commit b9bf5f1f57
)
This commit is contained in:
parent
5ccc0c06c0
commit
1cbe702e84
|
@ -603,7 +603,22 @@ class Connection(base.Connection):
|
|||
|
||||
session = self._engine_facade.get_session()
|
||||
engine = self._engine_facade.get_engine()
|
||||
query = session.query(models.FullSample)
|
||||
query = session.query(models.Sample.timestamp,
|
||||
models.Sample.recorded_at,
|
||||
models.Sample.message_id,
|
||||
models.Sample.message_signature,
|
||||
models.Sample.volume.label('counter_volume'),
|
||||
models.Meter.name.label('counter_name'),
|
||||
models.Meter.type.label('counter_type'),
|
||||
models.Meter.unit.label('counter_unit'),
|
||||
models.Resource.source_id,
|
||||
models.Resource.user_id,
|
||||
models.Resource.project_id,
|
||||
models.Resource.resource_metadata,
|
||||
models.Resource.resource_id).join(
|
||||
models.Meter, models.Meter.id == models.Sample.meter_id).join(
|
||||
models.Resource,
|
||||
models.Resource.internal_id == models.Sample.resource_id)
|
||||
transformer = sql_utils.QueryTransformer(models.FullSample, query,
|
||||
dialect=engine.dialect.name)
|
||||
if filter_expr is not None:
|
||||
|
|
|
@ -20,7 +20,7 @@ from oslo_utils import timeutils
|
|||
import six
|
||||
from sqlalchemy import (Column, Integer, String, ForeignKey, Index,
|
||||
UniqueConstraint, BigInteger)
|
||||
from sqlalchemy import event, select
|
||||
from sqlalchemy import event
|
||||
from sqlalchemy import Float, Boolean, Text, DateTime
|
||||
from sqlalchemy.dialects.mysql import DECIMAL
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
@ -221,29 +221,23 @@ class Sample(Base):
|
|||
message_id = Column(String(1000))
|
||||
|
||||
|
||||
class FullSample(Base):
|
||||
"""Mapper model.
|
||||
|
||||
It's needed as many of the filters work against raw data which is split
|
||||
between Meter, Sample, and Resource tables
|
||||
"""
|
||||
meter = Meter.__table__
|
||||
sample = Sample.__table__
|
||||
resource = Resource.__table__
|
||||
__table__ = (select([sample.c.id, meter.c.name.label('counter_name'),
|
||||
meter.c.type.label('counter_type'),
|
||||
meter.c.unit.label('counter_unit'),
|
||||
sample.c.volume.label('counter_volume'),
|
||||
resource.c.resource_id, resource.c.source_id,
|
||||
resource.c.user_id, resource.c.project_id,
|
||||
resource.c.resource_metadata, resource.c.internal_id,
|
||||
sample.c.timestamp, sample.c.message_id,
|
||||
sample.c.message_signature, sample.c.recorded_at])
|
||||
.select_from(
|
||||
sample.join(meter, sample.c.meter_id == meter.c.id).join(
|
||||
resource,
|
||||
sample.c.resource_id == resource.c.internal_id))
|
||||
.alias())
|
||||
class FullSample(object):
|
||||
"""A fake model for query samples."""
|
||||
id = Sample.id
|
||||
timestamp = Sample.timestamp
|
||||
message_id = Sample.message_id
|
||||
message_signature = Sample.message_signature
|
||||
recorded_at = Sample.recorded_at
|
||||
counter_name = Meter.name
|
||||
counter_type = Meter.type
|
||||
counter_unit = Meter.unit
|
||||
counter_volume = Sample.volume
|
||||
resource_id = Resource.resource_id
|
||||
source_id = Resource.source_id
|
||||
user_id = Resource.user_id
|
||||
project_id = Resource.project_id
|
||||
resource_metadata = Resource.resource_metadata
|
||||
internal_id = Resource.internal_id
|
||||
|
||||
|
||||
class Alarm(Base):
|
||||
|
|
Loading…
Reference in New Issue