This commit is contained in:
decent-engineer-decent-datascientist 2025-06-22 00:13:10 +09:00 committed by GitHub
commit ceef37fede
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 82 additions and 5 deletions

View File

@ -0,0 +1,57 @@
"""Add performance indexes to chat, tag, and function tables
---
Database Indexing & Migration Instructions
------------------------------------------
Open-WebUI now automatically creates indexes on key columns in the `chat`, `tag`, and `function` tables for improved performance with SQLite and PostgreSQL.
**For existing installations:**
Apply this migration to add the new indexes to your database:
alembic upgrade head
This will significantly speed up filtering, sorting, and joining operations as your data grows.
---
Revision ID: 20250619_add_indexes
Revises:
Create Date: 2025-06-19
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '20250619_add_indexes'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# Chat table indexes
op.create_index('folder_id_idx', 'chat', ['folder_id'])
op.create_index('user_id_pinned_idx', 'chat', ['user_id', 'pinned'])
op.create_index('user_id_archived_idx', 'chat', ['user_id', 'archived'])
op.create_index('updated_at_user_id_idx', 'chat', ['updated_at', 'user_id'])
op.create_index('folder_id_user_id_idx', 'chat', ['folder_id', 'user_id'])
# Tag table index
op.create_index('user_id_idx', 'tag', ['user_id'])
# Function table index
op.create_index('is_global_idx', 'function', ['is_global'])
def downgrade():
# Chat table indexes
op.drop_index('folder_id_idx', table_name='chat')
op.drop_index('user_id_pinned_idx', table_name='chat')
op.drop_index('user_id_archived_idx', table_name='chat')
op.drop_index('updated_at_user_id_idx', table_name='chat')
op.drop_index('folder_id_user_id_idx', table_name='chat')
# Tag table index
op.drop_index('user_id_idx', table_name='tag')
# Function table index
op.drop_index('is_global_idx', table_name='function')

View File

@ -9,7 +9,7 @@ from open_webui.models.tags import TagModel, Tag, Tags
from open_webui.env import SRC_LOG_LEVELS from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Boolean, Column, String, Text, JSON from sqlalchemy import BigInteger, Boolean, Column, String, Text, JSON, Index
from sqlalchemy import or_, func, select, and_, text from sqlalchemy import or_, func, select, and_, text
from sqlalchemy.sql import exists from sqlalchemy.sql import exists
@ -39,6 +39,20 @@ class Chat(Base):
meta = Column(JSON, server_default="{}") meta = Column(JSON, server_default="{}")
folder_id = Column(Text, nullable=True) folder_id = Column(Text, nullable=True)
__table_args__ = (
# Performance indexes for common queries
# WHERE folder_id = ...
Index('folder_id_idx', 'folder_id'),
# WHERE user_id = ... AND pinned = ...
Index('user_id_pinned_idx', 'user_id', 'pinned'),
# WHERE user_id = ... AND archived = ...
Index('user_id_archived_idx', 'user_id', 'archived'),
# WHERE user_id = ... ORDER BY updated_at DESC
Index('updated_at_user_id_idx', 'updated_at', 'user_id'),
# WHERE folder_id = ... AND user_id = ...
Index('folder_id_user_id_idx', 'folder_id', 'user_id'),
)
class ChatModel(BaseModel): class ChatModel(BaseModel):
model_config = ConfigDict(from_attributes=True) model_config = ConfigDict(from_attributes=True)

View File

@ -6,7 +6,7 @@ from open_webui.internal.db import Base, JSONField, get_db
from open_webui.models.users import Users from open_webui.models.users import Users
from open_webui.env import SRC_LOG_LEVELS from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Boolean, Column, String, Text from sqlalchemy import BigInteger, Boolean, Column, String, Text, Index
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"]) log.setLevel(SRC_LOG_LEVELS["MODELS"])
@ -31,6 +31,10 @@ class Function(Base):
updated_at = Column(BigInteger) updated_at = Column(BigInteger)
created_at = Column(BigInteger) created_at = Column(BigInteger)
__table_args__ = (
Index('is_global_idx', 'is_global'),
)
class FunctionMeta(BaseModel): class FunctionMeta(BaseModel):
description: Optional[str] = None description: Optional[str] = None

View File

@ -8,7 +8,7 @@ from open_webui.internal.db import Base, get_db
from open_webui.env import SRC_LOG_LEVELS from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Column, String, JSON, PrimaryKeyConstraint from sqlalchemy import BigInteger, Column, String, JSON, PrimaryKeyConstraint, Index
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"]) log.setLevel(SRC_LOG_LEVELS["MODELS"])
@ -24,8 +24,10 @@ class Tag(Base):
user_id = Column(String) user_id = Column(String)
meta = Column(JSON, nullable=True) meta = Column(JSON, nullable=True)
# Unique constraint ensuring (id, user_id) is unique, not just the `id` column __table_args__ = (
__table_args__ = (PrimaryKeyConstraint("id", "user_id", name="pk_id_user_id"),) PrimaryKeyConstraint("id", "user_id", name="pk_id_user_id"),
Index('user_id_idx', 'user_id'),
)
class TagModel(BaseModel): class TagModel(BaseModel):