Я бы хотел хранить большее количество временных меток с плавающей запятой в виде стандартных временных меток 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()