换过之后页面加载速度什么的会有提升么
很快的。
之前左边的对话条目要好久,换完之后刷刷的。
还是重新设置方便,5分钟搞定
我刚刚试了一下,完整迁移成功了,似乎并不需要单独导出配置,所有对话、配置都在数据库里。
PostgreSQL 数据库迁移指南
-
创建一个空的 PostgreSQL 数据库。
-
关闭 Open WebUI。
-
设置
DATABASE_URL
环境变量,指向新创建的 PostgreSQL 数据库。
environment:
- DATABASE_URL=postgres://用户名:口令@ip:5432/数据库名
- DATABASE_POOL_SIZE=10
- DATABASE_POOL_MAX_OVERFLOW=20
- ENABLE_OLLAMA_API=false
-
启动 Open WebUI 并尝试访问网站。这应该会强制创建数据库的图表。
-
再次关闭 Open WebUI。
-
在某个位置创建一个新目录。
mkdir sqlite-to-postgres-migration cd sqlite-to-postgres-migration
-
初始化一个新的 Node.js 项目:
npm init -y npm install sqlite3 pg
-
从现有的 WebUI 部署中复制
webui.db
文件。该文件位于:<webui-root>/backend/data/webui.db
-
在新目录中创建以下脚本(修改原先数据库路径以及postgres数据库连接信息),例如命名为
migrate.js
:
// Credit goes to Anthropic Claude Sonnet 3.5 for helping write this script!
const sqlite3 = require('sqlite3').verbose();
const { Client } = require('pg');
const fs = require('fs').promises;
// Configuration
const SQLITE_DB_PATH = 'webui.db'; // 改成webui.db所在目录,默认为当前目录
//这里修改数据库相关信息
const PG_CONFIG = {
host: 'CONFIGURE ME',
port: 5432,
database: 'CONFIGURE ME',
user: 'CONFIGURE ME',
password: 'CONFIGURE ME',
ssl: false
};
// Helper function to convert SQLite types to PostgreSQL types
function sqliteToPgType(sqliteType) {
switch (sqliteType.toUpperCase()) {
case 'INTEGER': return 'INTEGER';
case 'REAL': return 'DOUBLE PRECISION';
case 'TEXT': return 'TEXT';
case 'BLOB': return 'BYTEA';
default: return 'TEXT';
}
}
// Helper function to handle reserved keywords
function getSafeIdentifier(identifier) {
const reservedKeywords = ['user', 'group', 'order', 'table', 'select', 'where', 'from', 'index', 'constraint'];
return reservedKeywords.includes(identifier.toLowerCase()) ? `"${identifier}"` : identifier;
}
async function migrate() {
// Connect to SQLite database
const sqliteDb = new sqlite3.Database(SQLITE_DB_PATH);
// Connect to PostgreSQL database
const pgClient = new Client(PG_CONFIG);
await pgClient.connect();
try {
// Get list of tables from SQLite
const tables = await new Promise((resolve, reject) => {
sqliteDb.all("SELECT name FROM sqlite_master WHERE type='table'", (err, rows) => {
if (err) reject(err);
else resolve(rows);
});
});
for (const table of tables) {
const tableName = table.name;
// Skip "migratehistory" and "alembic_version" tables
if (tableName === "migratehistory" || tableName === "alembic_version") {
console.log(`Skipping table: ${tableName}`);
continue;
}
const safeTableName = getSafeIdentifier(tableName);
console.log(`Checking table: ${tableName}`);
// Check if table exists in PostgreSQL and has any rows
const result = await pgClient.query(`SELECT COUNT(*) FROM ${safeTableName}`);
const rowCount = parseInt(result.rows[0].count, 10);
if (rowCount > 0) {
console.log(`Skipping table: ${tableName} because it has ${rowCount} existing rows`);
continue;
}
console.log(`Migrating table: ${tableName}`);
// Get table schema from PostgreSQL to determine column types
const pgSchema = await pgClient.query(
`SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = $1`,
[safeTableName]
);
const pgColumnTypes = {};
pgSchema.rows.forEach(col => {
pgColumnTypes[col.column_name] = col.data_type;
});
// Get table schema from SQLite
const schema = await new Promise((resolve, reject) => {
sqliteDb.all(`PRAGMA table_info(${tableName})`, (err, rows) => {
if (err) reject(err);
else resolve(rows);
});
});
// Create table in PostgreSQL if it doesn't exist
const columns = schema.map(col => `${getSafeIdentifier(col.name)} ${sqliteToPgType(col.type)}`).join(', ');
await pgClient.query(`CREATE TABLE IF NOT EXISTS ${safeTableName} (${columns})`);
// Get data from SQLite
const rows = await new Promise((resolve, reject) => {
sqliteDb.all(`SELECT * FROM ${tableName}`, (err, rows) => {
if (err) reject(err);
else resolve(rows);
});
});
// Insert data into PostgreSQL
for (const row of rows) {
const columns = Object.keys(row).map(getSafeIdentifier).join(', ');
const values = Object.entries(row).map(([key, value]) => {
const columnType = pgColumnTypes[key]; // Get the type of the column in PostgreSQL
// Handle boolean conversion for PostgreSQL
if (columnType === 'boolean') {
return value === 1 ? 'true' : 'false'; // Explicitly convert 1 to 'true' and 0 to 'false'
}
if (value === null) return 'NULL'; // Handle NULL values
return typeof value === 'string' ? `'${value.replace(/'/g, "''")}'` : value; // Handle string escaping
}).join(', ');
// Insert data into PostgreSQL
await pgClient.query(`INSERT INTO ${safeTableName} (${columns}) VALUES (${values})`);
}
console.log(`Migrated ${rows.length} rows from ${tableName}`);
}
console.log("Migration completed successfully!");
} catch (error) {
console.error("Error during migration:", error);
} finally {
// Close database connections
sqliteDb.close();
await pgClient.end();
}
}
migrate();
- 运行脚本
node migrate.js
正常的话则不会报错,此时运行open-webui发现迁移成功,配置、对话都在
单独导一下对话,安全,毕竟重要数据是对话。
挺好的 抽空迁移了下 谢谢分享
20G的对话数据怎么迁移
感谢分享,有空迁移一下
你20G的对话数据,Open webui是怎么跑的啊。 机器强悍。。。。。
写程序读sqllite,写psql,1000条一提交。
你这不是psql了。 你现在不需要psql了, 要需要 Greenplum。
我1g内存的小鸡部署上去直接卡死,ssh都连不上去了,只能重装
可以给我们测试一下 Greenplum,你这也是大模型和大数据相结合了。
用Greenplum好处,就是不用再关心数据存储了。
这是啥 新出的吗 之前没这个配置
Greenplum是 psql的大数据版本,接口兼容 psql的。
简单了解了下 不知道能优化多少 有空看看
主要是解决存储问题,不用再关心数据备份,数据过大等等大量数据引发的问题。
对话可以先设置里导出,然后新数据库里再设置界面上导入啊?下午试了下,配置可以导入,对话好像没反应。