File size: 7,608 Bytes
cd9bca9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# 🔄 PostgreSQL 直連遷移指南

本文件說明如何從 Supabase SDK 遷移到 PostgreSQL 直連的詳細步驟和注意事項。

## 📋 遷移概述

### 變更內容
- ✅ 移除 Supabase Python SDK 依賴
- ✅ 新增 SQLAlchemy + psycopg 直連
- ✅ 重構資料庫服務層
- ✅ 新增 ORM 模型定義
- ✅ 支援 Alembic 資料庫遷移

### 優勢
- 🚀 **更好的效能**: 直連減少中間層開銷
- 🔧 **更多控制**: 完整的 SQL 查詢控制
- 📊 **ORM 支援**: SQLAlchemy 提供強大的 ORM 功能
- 🔄 **遷移管理**: Alembic 提供版本化的資料庫遷移
- 🛡️ **連線池**: 自動連線池管理

## 🔑 環境變數更新

### 舊的 Supabase 設定
```bash
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-anon-key
```

### 新的 PostgreSQL 設定
```bash
DB_HOST=db.your-project.supabase.co
DB_PORT=6543
DB_NAME=postgres
DB_USER=postgres
DB_PASSWORD=your-database-password
```

## 🔍 如何取得 PostgreSQL 連線資訊

### 從 Supabase Dashboard 取得

1. **登入 Supabase Dashboard**
   - 前往 [Supabase Dashboard](https://supabase.com/dashboard)
   - 選擇您的專案

2. **取得連線資訊**
   - 前往 "Settings" → "Database"
   - 在 "Connection info" 區域找到:
     - **Host**: `db.your-project-ref.supabase.co`
     - **Port**: `6543` (PostgreSQL 直連埠)
     - **Database**: `postgres`
     - **User**: `postgres`
     - **Password**: 您設定的資料庫密碼

3. **連線字串範例**
   ```
   postgresql://postgres:your-password@db.your-project-ref.supabase.co:6543/postgres
   ```

### 從其他 PostgreSQL 提供商取得

如果您使用其他 PostgreSQL 服務:
- **AWS RDS**: 在 RDS Console 中查看端點資訊
- **Google Cloud SQL**: 在 Cloud Console 中查看連線詳情
- **Azure Database**: 在 Azure Portal 中查看連線字串
- **Railway/Render**: 在專案設定中查看資料庫資訊

## 🛠️ 部署步驟

### 1. 更新環境變數

在 Hugging Face Spaces 的 Settings 中更新:

```bash
# 移除舊的 Supabase 設定
# SUPABASE_URL=...
# SUPABASE_KEY=...

# 新增 PostgreSQL 設定
DB_HOST=db.your-project-ref.supabase.co
DB_PORT=6543
DB_NAME=postgres
DB_USER=postgres
DB_PASSWORD=your-database-password

# 其他設定保持不變
LINE_CHANNEL_ACCESS_TOKEN=your-line-token
LINE_CHANNEL_SECRET=your-line-secret
OPENROUTER_API_KEY=your-openrouter-key
OPENROUTER_MODEL=anthropic/claude-3-haiku
```

### 2. 初始化資料庫

部署後,執行資料庫初始化:

```bash
# 在容器中執行
python -m backend.database.init_db
```

或者透過 API 端點觸發初始化(如果實作了相關端點)。

### 3. 驗證連線

檢查健康檢查端點:
```bash
curl https://your-space-url.hf.space/health
```

應該會看到:
```json
{
  "status": "healthy",
  "message": "LINE Bot API is operational", 
  "database": "connected",
  "database_url": "postgresql://your-host:6543/postgres"
}
```

## 📊 資料庫模型對應

### 新的 SQLAlchemy 模型

```python
# backend/database/models.py

class User(Base):
    __tablename__ = "users"
    user_id = Column(String(255), primary_key=True)
    name = Column(String(255))
    email = Column(String(255))
    # ... 其他欄位

class Product(Base):
    __tablename__ = "products"
    product_id = Column(Integer, primary_key=True)
    name = Column(String(255), nullable=False)
    price = Column(DECIMAL(10, 2), nullable=False)
    # ... 其他欄位
```

### 資料表關聯

```python
# 一對多關聯
class User(Base):
    orders = relationship("Order", back_populates="user")

class Order(Base):
    user = relationship("User", back_populates="orders")
    order_items = relationship("OrderItem", back_populates="order")
```

## 🔄 API 變更

### 查詢方式變更

#### 舊的 Supabase 方式
```python
result = supabase.table("users").select("*").eq("name", "張三").execute()
```

#### 新的 SQLAlchemy 方式
```python
db = get_database_session()
users = db.query(User).filter(User.name == "張三").all()
```

### 錯誤處理改進

```python
def database_operation():
    db = None
    try:
        db = get_database_session()
        # 資料庫操作
        result = db.query(User).all()
        db.commit()
        return result
    except Exception as e:
        if db:
            db.rollback()
        logger.error(f"資料庫操作失敗: {str(e)}")
        raise
    finally:
        if db:
            close_database_session(db)
```

## 🚀 效能優化

### 連線池設定

```python
# backend/database/connection.py
engine = create_engine(
    settings.DATABASE_URL,
    pool_size=10,          # 連線池大小
    max_overflow=20,       # 最大溢出連線
    pool_pre_ping=True,    # 連線前檢查
    pool_recycle=3600,     # 1小時後回收連線
)
```

### 查詢優化

```python
# 使用 eager loading 避免 N+1 查詢
from sqlalchemy.orm import joinedload

users_with_orders = db.query(User).options(
    joinedload(User.orders)
).all()

# 使用索引優化查詢
# 在模型中定義索引
class User(Base):
    __tablename__ = "users"
    name = Column(String(255), index=True)  # 建立索引
```

## 🔧 開發工具

### Alembic 遷移

```bash
# 初始化 Alembic
alembic init alembic

# 建立遷移檔案
alembic revision --autogenerate -m "Initial migration"

# 執行遷移
alembic upgrade head

# 回滾遷移
alembic downgrade -1
```

### 本地開發

```bash
# 安裝依賴
pip install -r requirements.txt

# 設定環境變數
export DB_HOST=localhost
export DB_PORT=5432
export DB_NAME=linebot_dev
export DB_USER=postgres
export DB_PASSWORD=password

# 初始化資料庫
python -m backend.database.init_db

# 執行應用程式
uvicorn backend.main:app --reload --port 7860
```

## 🛡️ 安全性考量

### 連線安全

1. **使用 SSL 連線**
   ```python
   DATABASE_URL = f"postgresql+psycopg://{user}:{password}@{host}:{port}/{db}?sslmode=require"
   ```

2. **限制資料庫權限**
   - 建立專用的應用程式使用者
   - 只授予必要的資料表權限
   - 定期輪換密碼

3. **連線字串保護**
   - 使用環境變數儲存敏感資訊
   - 避免在日誌中記錄連線字串
   - 使用密碼管理工具

## 📈 監控與除錯

### 日誌設定

```python
# 啟用 SQLAlchemy 日誌
engine = create_engine(
    settings.DATABASE_URL,
    echo=settings.DEBUG,  # 在 DEBUG 模式下顯示 SQL
)
```

### 效能監控

```python
import time
from functools import wraps

def monitor_db_performance(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        execution_time = time.time() - start_time
        logger.info(f"{func.__name__} 執行時間: {execution_time:.2f}秒")
        return result
    return wrapper
```

## 🚨 常見問題

### Q: 連線失敗怎麼辦?
A: 檢查以下項目:
1. 主機名稱和埠號是否正確
2. 使用者名稱和密碼是否正確
3. 資料庫是否允許外部連線
4. 防火牆設定是否正確

### Q: 效能比 Supabase SDK 慢?
A: 可能原因:
1. 連線池設定不當
2. 查詢未優化
3. 缺少適當的索引
4. 網路延遲問題

### Q: 如何處理資料庫遷移?
A: 使用 Alembic:
1. 建立遷移腳本
2. 在部署前測試遷移
3. 備份資料庫
4. 執行遷移

## 📞 技術支援

如果遇到問題:
1. 檢查應用程式日誌
2. 驗證環境變數設定
3. 測試資料庫連線
4. 參考 SQLAlchemy 官方文件

---

**注意**: 遷移前請務必備份您的資料庫,並在測試環境中驗證所有功能正常運作。