SQLalchemy: автоматически применять фильтры к столбцам - PullRequest
0 голосов
/ 13 ноября 2018

Я бы хотел хранить большее количество временных меток с плавающей запятой в виде стандартных временных меток postgresql, используя пользовательский тип данных SQLalchemy. Я видел возможные решения, такие как Определение таблицы с помощью sqlalchemy с отметкой времени mysql unix . Что мне не нравится в этом, так это то, что он довольно неэффективен, поскольку он конвертирует число с плавающей точкой в ​​объект времени и обратно в метку времени, тогда как это должно быть просто «умножить на 1e6, добавить константу и привести к int» -конверсия, которая по времени должна быть близка к нулю. В то время как

%timeit float(calendar.timegm(datetime.datetime.utcfromtimestamp(1542098001).timetuple()))

тратит что-то вроде 2us за звонок на моей машине. Использование postgresql to_timestamp и extract(epoch from timestamp_col) должно быть намного быстрее и лучше подходить для аналитических рабочих нагрузок. Есть ли способ в SQLalchemy, который может автоматически применять эти преобразования на уровне SQL для всех операторов, влияющих на этот столбец? Я также подумал об использовании простого поля с плавающей запятой для хранения, но я бы предпочел использовать функции времени для доступа к данным.

import time
from datetime import datetime
from calendar import timegm
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, String, Integer, DateTime, TypeDecorator, create_engine


class Timestamp(TypeDecorator):
    impl = DateTime

    def process_bind_param(self, value, dialect):
        if value is None:
            return
        elif isinstance(value, datetime):
            return value
        elif isinstance(value, (int, float)):
            return datetime.utcfromtimestamp(value)
        raise TypeError("Any form of time object required, but received {}".format(type(value).__name__))

    def process_result_value(self, value, dialect):
        if value is None:
            return None # support nullability
        elif isinstance(value, datetime):
            return float(timegm(value.timetuple()))
        raise vn.ValidationTypeError("datetime object required, but received {}".format(type(value).__name__))


Base = declarative_base()

class SystemLog(Base):
    __tablename__ = 'systemlog'
    id = Column(Integer, primary_key=True)
    time = Column(Timestamp, index=True, nullable=False, default=datetime.utcnow)
    type = Column(String(20))
    message = Column(String(2000))


engine = create_engine('sqlite://')
Session = sessionmaker(bind=engine)

s = Session()
Base.metadata.create_all(engine)
s.commit()

start_time = time.time()
sample_data = [SystemLog(time=start_time + i) for i in xrange(10000)]
s.add_all(sample_data)
s.commit()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...