perf: SQLite WAL + 复合索引 + GZip + scheduler jitter + 构建缓存
This commit is contained in:
+40
-1
@@ -1,4 +1,4 @@
|
||||
from sqlalchemy import create_engine, inspect, text
|
||||
from sqlalchemy import create_engine, event, inspect, text
|
||||
from sqlalchemy.orm import sessionmaker, DeclarativeBase
|
||||
from app.config import get_settings
|
||||
|
||||
@@ -8,6 +8,21 @@ engine = create_engine(
|
||||
settings.database_url,
|
||||
connect_args={"check_same_thread": False},
|
||||
)
|
||||
|
||||
# ── SQLite 性能 PRAGMA(WAL + 缓存 + 超时) ──
|
||||
@event.listens_for(engine, "connect", insert=True)
|
||||
def _set_sqlite_pragma(dbapi_connection, connection_record):
|
||||
if engine.dialect.name != "sqlite":
|
||||
return
|
||||
cursor = dbapi_connection.cursor()
|
||||
cursor.execute("PRAGMA journal_mode=WAL;")
|
||||
cursor.execute("PRAGMA synchronous=NORMAL;")
|
||||
cursor.execute("PRAGMA busy_timeout=5000;")
|
||||
cursor.execute("PRAGMA foreign_keys=ON;")
|
||||
cursor.execute("PRAGMA cache_size=-20000;") # 20 MB page cache
|
||||
cursor.execute("PRAGMA mmap_size=67108864;") # 64 MB(小内存容器友好)
|
||||
cursor.close()
|
||||
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
|
||||
@@ -28,11 +43,35 @@ def init_db():
|
||||
# import models so SQLAlchemy registers them
|
||||
from app.models import admin_user, upstream, snapshot, webhook_config, notification_log, custom_page, website, revoked_token, upstream_key # noqa: F401
|
||||
Base.metadata.create_all(bind=engine)
|
||||
_ensure_indexes()
|
||||
_migrate_custom_pages()
|
||||
_migrate_upstreams()
|
||||
_migrate_upstream_generated_keys()
|
||||
|
||||
|
||||
# ── 已有数据库幂等索引迁移 ─────────────────────────────────
|
||||
_NEW_INDEXES = [
|
||||
"CREATE INDEX IF NOT EXISTS ix_snapshot_upstream_captured ON upstream_rate_snapshots(upstream_id, captured_at DESC)",
|
||||
"CREATE INDEX IF NOT EXISTS ix_notif_event_created ON notification_logs(event_type, created_at DESC)",
|
||||
"CREATE INDEX IF NOT EXISTS ix_notif_status_created ON notification_logs(status, created_at DESC)",
|
||||
"CREATE INDEX IF NOT EXISTS ix_sync_website_created ON website_sync_logs(website_id, created_at DESC)",
|
||||
"CREATE INDEX IF NOT EXISTS ix_sync_binding_created ON website_sync_logs(binding_id, created_at DESC)",
|
||||
"CREATE INDEX IF NOT EXISTS ix_upstream_enabled ON upstreams(enabled)",
|
||||
"CREATE INDEX IF NOT EXISTS ix_key_upstream_name ON upstream_generated_keys(upstream_id, key_name)",
|
||||
]
|
||||
|
||||
|
||||
def _ensure_indexes() -> None:
|
||||
"""创建 InitDB 时可能未包含的复合索引,幂等执行。"""
|
||||
with engine.begin() as conn:
|
||||
for stmt in _NEW_INDEXES:
|
||||
try:
|
||||
conn.execute(text(stmt))
|
||||
except Exception:
|
||||
logger = __import__("logging").getLogger(__name__)
|
||||
logger.warning("index creation failed (non-fatal): %s", stmt[:60])
|
||||
|
||||
|
||||
def _migrate_custom_pages():
|
||||
"""Apply small SQLite-safe migrations for deployments without Alembic."""
|
||||
inspector = inspect(engine)
|
||||
|
||||
Reference in New Issue
Block a user