|
@@ -0,0 +1,72 @@
|
|
|
|
|
+package vrtxsql
|
|
|
|
|
+
|
|
|
|
|
+import (
|
|
|
|
|
+ "database/sql"
|
|
|
|
|
+ "fmt"
|
|
|
|
|
+ "testing"
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+// 生产形态仿真: monitor_metrics 同款结构 + GORM 驱动路径 + 周期清理(触发索引重建) + 持续插入。
|
|
|
|
|
+func TestProdShapeSimulation(t *testing.T) {
|
|
|
|
|
+ dsn := t.TempDir() + "/prod.db"
|
|
|
|
|
+ db, err := sql.Open("vrtx", dsn)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ t.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ defer db.Close()
|
|
|
|
|
+ if _, err := db.Exec(`CREATE TABLE monitor_metrics (
|
|
|
|
|
+ id BIGINT PRIMARY KEY,
|
|
|
|
|
+ service_name VARCHAR(128),
|
|
|
|
|
+ ts BIGINT,
|
|
|
|
|
+ cnt BIGINT)`); err != nil {
|
|
|
|
|
+ t.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if _, err := db.Exec(`CREATE INDEX idx_name ON monitor_metrics (service_name)`); err != nil {
|
|
|
|
|
+ t.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if _, err := db.Exec(`CREATE INDEX idx_ts ON monitor_metrics (ts)`); err != nil {
|
|
|
|
|
+ t.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ // GORM 形态: Prepare + 批量循环 Exec (5秒一轮监控的密度, 放大 40 轮)
|
|
|
|
|
+ stmt, err := db.Prepare(`INSERT INTO monitor_metrics (id, service_name, ts, cnt) VALUES (?, ?, ?, ?)`)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ t.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ defer stmt.Close()
|
|
|
|
|
+ id := int64(0)
|
|
|
|
|
+ insertRound := func(n int, base int64) {
|
|
|
|
|
+ for i := 0; i < n; i++ {
|
|
|
|
|
+ id++
|
|
|
|
|
+ svc := fmt.Sprintf("service-%02d-with-a-fairly-long-name-for-wide-secondary-keys", i%17)
|
|
|
|
|
+ if _, err := stmt.Exec(id, svc, base+int64(i), int64(i)); err != nil {
|
|
|
|
|
+ t.Fatalf("插入 id=%d: %v", id, err)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ deleteBelow := func(bound int64) {
|
|
|
|
|
+ if _, err := db.Exec(`DELETE FROM monitor_metrics WHERE ts < ?`, bound); err != nil {
|
|
|
|
|
+ t.Fatalf("清理 ts<%d: %v", bound, err)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for round := 0; round < 40; round++ {
|
|
|
|
|
+ insertRound(200, int64(round*1000)) // 每轮 200 行 (一行 total + 每服务行)
|
|
|
|
|
+ deleteBelow(int64(round*1000 - 500)) // 周期清理 → 触发批量删+索引重建
|
|
|
|
|
+ }
|
|
|
|
|
+ // 校验: 只有最后一轮的 200 行存活 (早期轮次被后续清理删光)
|
|
|
|
|
+ var total int64
|
|
|
|
|
+ if err := db.QueryRow(`SELECT COUNT(*) FROM monitor_metrics`).Scan(&total); err != nil {
|
|
|
|
|
+ t.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if total != 200 {
|
|
|
|
|
+ t.Fatalf("行数不一致: total=%d 期望 200", total)
|
|
|
|
|
+ }
|
|
|
|
|
+ var n int64
|
|
|
|
|
+ if err := db.QueryRow(`SELECT COUNT(*) FROM monitor_metrics WHERE service_name = ?`,
|
|
|
|
|
+ "service-05-with-a-fairly-long-name-for-wide-secondary-keys").Scan(&n); err != nil {
|
|
|
|
|
+ t.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if n == 0 {
|
|
|
|
|
+ t.Fatal("二级索引等值查 0 行")
|
|
|
|
|
+ }
|
|
|
|
|
+ t.Logf("仿真完成: 累计插入 %d 行, 存活 %d, 索引等值命中 %d", id, total, n)
|
|
|
|
|
+}
|