Skip to content

Commit 7b63676

Browse files
Duckdb optimize (#899)
1 parent 24b74c2 commit 7b63676

8 files changed

Lines changed: 69 additions & 20 deletions

File tree

build/Dockerfile.sql-analyzer

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ FROM golang:1.25 AS builder
33

44
ARG GOPROXY
55
ARG GOSUMDB
6+
ARG ASAN_ENABLED
67

78
WORKDIR /workspace
89
# copy everything
@@ -12,12 +13,20 @@ COPY . .
1213
RUN if [ -n "$GOPROXY" ]; then go env -w GOPROXY=$GOPROXY; fi
1314
RUN if [ -n "$GOSUMDB" ]; then go env -w GOSUMDB=$GOSUMDB; fi
1415

15-
RUN make sql-analyzer
16+
RUN ASAN_ENABLED=$ASAN_ENABLED make sql-analyzer
1617

1718
# start build docker image
1819
# Use ubuntu:24.04 as the base image
1920
FROM ubuntu:24.04
2021

22+
ARG ASAN_ENABLED
23+
# Install libasan if ASAN_ENABLED is set
24+
RUN if [ -n "$ASAN_ENABLED" ]; then \
25+
apt-get update && \
26+
apt-get install -y libasan8 && \
27+
rm -rf /var/lib/apt/lists/*; \
28+
fi
29+
2130
# Set working directory
2231
WORKDIR /app
2332

cmd/sql-analyzer/main.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func startHttpServer(ctx context.Context, logger *logrus.Logger) *webserver.HTTP
6464
logger.Info("Successfully registered router")
6565
go func() {
6666
err := httpServer.Run()
67-
if err != nil {
67+
if err != nil && err != http.ErrServerClosed {
6868
logger.WithError(err).Errorln("Start server failed")
6969
os.Exit(1)
7070
}
@@ -200,6 +200,17 @@ func main() {
200200
}
201201
}
202202

203+
// Configure DuckDB max open conns
204+
duckDBMaxOpenConns := 10
205+
duckDBMaxOpenConnsStr := os.Getenv("DUCKDB_MAX_OPEN_CONNS")
206+
if duckDBMaxOpenConnsStr != "" {
207+
if val, err := strconv.Atoi(duckDBMaxOpenConnsStr); err == nil && val > 0 {
208+
duckDBMaxOpenConns = val
209+
} else {
210+
analyzerLogger.Warnf("Invalid DUCKDB_MAX_OPEN_CONNS value '%s', using default of 10.", duckDBMaxOpenConnsStr)
211+
}
212+
}
213+
203214
config := &config.Config{
204215
Namespace: namespace,
205216
OBTenant: obtenant,
@@ -211,10 +222,11 @@ func main() {
211222
QueueSize: queueSize,
212223
WorkerNum: workerNum,
213224
PlanCacheSize: planCacheSize,
225+
DuckDBMaxOpenConns: duckDBMaxOpenConns,
214226
}
215227

216228
// Initialize Stores
217-
if err := store.InitGlobalStores(ctx, config.DataPath, collectorLogger); err != nil {
229+
if err := store.InitGlobalStores(ctx, config, collectorLogger); err != nil {
218230
collectorLogger.Fatalf("Failed to initialize stores: %v", err)
219231
}
220232

internal/sql-analyzer/config/collector.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ type Config struct {
2626
SqlAuditLimit int
2727
SlowSqlThresholdMilliSeconds int
2828
PlanCacheSize int
29+
DuckDBMaxOpenConns int
2930
}

internal/sql-analyzer/const/sql/sql_plan.go

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,20 +82,35 @@ const (
8282
GetTablePrimaryKey = `SELECT column_name FROM oceanbase.__all_virtual_column WHERE tenant_id = ? AND table_id = ? and rowkey_position <> 0 ORDER BY rowkey_position`
8383
CheckPlanExistence = `SELECT COUNT(*) FROM sql_plan WHERE TENANT_ID = ? AND SVR_IP = ? AND SVR_PORT = ? AND PLAN_ID = ?`
8484
GetPlanStats = `
85+
WITH PlanAgg AS (
86+
SELECT
87+
TENANT_ID,
88+
SVR_IP,
89+
SVR_PORT,
90+
PLAN_ID,
91+
PLAN_HASH,
92+
MAX(GMT_CREATE) as GMT_CREATE,
93+
SUM(IO_COST) as IO_COST,
94+
SUM(CPU_COST) as CPU_COST,
95+
SUM(COST) as COST,
96+
SUM(REAL_COST) as REAL_COST
97+
FROM sql_plan
98+
WHERE SQL_ID = ?
99+
GROUP BY TENANT_ID, SVR_IP, SVR_PORT, PLAN_ID, PLAN_HASH
100+
)
85101
SELECT
86-
TENANT_ID,
87-
SVR_IP,
88-
SVR_PORT,
89-
PLAN_ID,
102+
MAX(TENANT_ID) as TENANT_ID,
103+
MAX(SVR_IP) as SVR_IP,
104+
MAX(SVR_PORT) as SVR_PORT,
105+
MAX(PLAN_ID) as PLAN_ID,
90106
PLAN_HASH,
91-
MIN(GMT_CREATE) as GMT_CREATE,
92-
SUM(IO_COST) as IO_COST,
93-
SUM(CPU_COST) as CPU_COST,
94-
SUM(COST) as COST,
95-
SUM(REAL_COST) as REAL_COST
96-
FROM sql_plan
97-
WHERE SQL_ID = ?
98-
GROUP BY TENANT_ID, SVR_IP, SVR_PORT, PLAN_ID, PLAN_HASH
107+
MAX(GMT_CREATE) as GMT_CREATE,
108+
CAST(AVG(IO_COST) AS BIGINT) as IO_COST,
109+
CAST(AVG(CPU_COST) AS BIGINT) as CPU_COST,
110+
CAST(AVG(COST) AS BIGINT) as COST,
111+
CAST(AVG(REAL_COST) AS BIGINT) as REAL_COST
112+
FROM PlanAgg
113+
GROUP BY PLAN_HASH
99114
`
100115
GetTableInfo = `
101116
SELECT

internal/sql-analyzer/store/global.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,23 @@ import (
1818
"path/filepath"
1919

2020
"github.com/sirupsen/logrus"
21+
22+
"github.com/oceanbase/ob-operator/internal/sql-analyzer/config"
2123
)
2224

2325
var (
2426
globalSqlAuditStore *SqlAuditStore
2527
globalPlanStore *PlanStore
2628
)
2729

28-
func InitGlobalStores(ctx context.Context, dataPath string, logger *logrus.Logger) error {
30+
func InitGlobalStores(ctx context.Context, conf *config.Config, logger *logrus.Logger) error {
2931
var err error
30-
globalSqlAuditStore, err = NewSqlAuditStore(ctx, filepath.Join(dataPath, "sql_audit"), logger)
32+
globalSqlAuditStore, err = NewSqlAuditStore(ctx, filepath.Join(conf.DataPath, "sql_audit"), conf.DuckDBMaxOpenConns, logger)
3133
if err != nil {
3234
return err
3335
}
3436

35-
globalPlanStore, err = NewPlanStore(ctx, filepath.Join(dataPath, "sql_plan"), logger)
37+
globalPlanStore, err = NewPlanStore(ctx, filepath.Join(conf.DataPath, "sql_plan"), conf.DuckDBMaxOpenConns, logger)
3638
if err != nil {
3739
return err
3840
}

internal/sql-analyzer/store/sql_audit.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,15 @@ type SqlAuditStore struct {
4444
Logger *logger.Logger
4545
}
4646

47-
func NewSqlAuditStore(c context.Context, path string, l *logger.Logger) (*SqlAuditStore, error) {
47+
func NewSqlAuditStore(c context.Context, path string, maxOpenConns int, l *logger.Logger) (*SqlAuditStore, error) {
4848
// Use an in-memory DuckDB database for operations.
4949
db, err := sql.Open("duckdb", "") // In-memory
5050
if err != nil {
5151
return nil, fmt.Errorf("failed to open in-memory duckdb: %w", err)
5252
}
5353

54+
db.SetMaxOpenConns(maxOpenConns)
55+
5456
// Set memory limit for in-memory DB
5557
conn, err := db.Conn(c)
5658
if err == nil {

internal/sql-analyzer/store/sql_plan.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (s *PlanStore) InitSqlPlanTable() error {
4242
return err
4343
}
4444

45-
func NewPlanStore(c context.Context, path string, l *logger.Logger) (*PlanStore, error) {
45+
func NewPlanStore(c context.Context, path string, maxOpenConns int, l *logger.Logger) (*PlanStore, error) {
4646
l.Infof("Using plan store at %s", path)
4747
if err := os.MkdirAll(path, 0755); err != nil {
4848
return nil, fmt.Errorf("failed to create data directory %s: %w", path, err)
@@ -77,6 +77,8 @@ func NewPlanStore(c context.Context, path string, l *logger.Logger) (*PlanStore,
7777
return nil, errors.Wrapf(err, "failed to open duckdb after retries at path %s", path)
7878
}
7979

80+
db.SetMaxOpenConns(maxOpenConns)
81+
8082
// Set memory limit
8183
memLimit := os.Getenv("DUCKDB_MEMORY_LIMIT")
8284
if memLimit == "" {

make/sql-analyzer.mk

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@ sql-analyzer-doc-gen: sql-analyzer-dep-install ## Generate swagger docs for sql-
1515
sql-analyzer: sql-analyzer-doc-gen
1616
@echo Building sql-analyzer...
1717
@mkdir -p bin
18+
ifneq ($(ASAN_ENABLED),)
19+
@echo "Building with AddressSanitizer..."
20+
CGO_ENABLED=1 CGO_CFLAGS="-fsanitize=address -g" CGO_LDFLAGS="-fsanitize=address" go build -tags dynamic -o bin/sql-analyzer cmd/sql-analyzer/main.go
21+
else
1822
@go build -o bin/sql-analyzer cmd/sql-analyzer/main.go
23+
endif
1924

2025
.PHONY: sql-analyzer-image
2126
sql-analyzer-image:
2227
$(eval DOCKER_BUILD_ARGS :=)
2328
$(if $(GOPROXY),$(eval DOCKER_BUILD_ARGS := --build-arg GOPROXY=$(GOPROXY)))
29+
$(if $(ASAN_ENABLED),$(eval DOCKER_BUILD_ARGS := $(DOCKER_BUILD_ARGS) --build-arg ASAN_ENABLED=$(ASAN_ENABLED)))
2430
docker build $(DOCKER_BUILD_ARGS) -t ${SQL_ANALYZER_IMG} -f build/Dockerfile.sql-analyzer .

0 commit comments

Comments
 (0)