mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-06-04 11:25:52 +08:00
95 lines
4.6 KiB
Markdown
95 lines
4.6 KiB
Markdown
# SQL
|
|
SigNoz utilizes a relational database to store metadata including organization information, user data and other settings.
|
|
|
|
## How to use it?
|
|
|
|
The database interface is defined in [SQLStore](/pkg/sqlstore/sqlstore.go). SigNoz leverages the Bun ORM to interact with the underlying database. To access the database instance, use the `BunDBCtx` function. For operations that require transactions across multiple database operations, use the `RunInTxCtx` function. This function embeds a transaction in the context, which propagates through various functions in the callback.
|
|
|
|
```go
|
|
type Thing struct {
|
|
bun.BaseModel
|
|
|
|
ID types.Identifiable `bun:",embed"`
|
|
SomeColumn string `bun:"some_column"`
|
|
TimeAuditable types.TimeAuditable `bun:",embed"`
|
|
OrgID string `bun:"org_id"`
|
|
}
|
|
|
|
func GetThing(ctx context.Context, id string) (*Thing, error) {
|
|
thing := new(Thing)
|
|
err := sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewSelect().
|
|
Model(thing).
|
|
Where("id = ?", id).
|
|
Scan(ctx)
|
|
|
|
return thing, err
|
|
}
|
|
|
|
func CreateThing(ctx context.Context, thing *Thing) error {
|
|
return sqlstore.
|
|
BunDBCtx(ctx).
|
|
NewInsert().
|
|
Model(thing).
|
|
Exec(ctx)
|
|
}
|
|
```
|
|
|
|
> 💡 **Note**: Always use line breaks while working with SQL queries to enhance code readability.
|
|
|
|
> 💡 **Note**: Always use the `new` function to create new instances of structs.
|
|
|
|
## What are hooks?
|
|
|
|
Hooks are user-defined functions that execute before and/or after specific database operations. These hooks are particularly useful for generating telemetry data such as logs, traces, and metrics, providing visibility into database interactions. Hooks are defined in the [SQLStoreHook](/pkg/sqlstore/sqlstore.go) interface.
|
|
|
|
## How is the schema designed?
|
|
|
|
SigNoz implements a star schema design with the organizations table as the central entity. All other tables link to the organizations table via foreign key constraints on the `org_id` column. This design ensures that every entity within the system is either directly or indirectly associated with an organization.
|
|
|
|
```mermaid
|
|
erDiagram
|
|
ORGANIZATIONS {
|
|
string id PK
|
|
timestamp created_at
|
|
timestamp updated_at
|
|
}
|
|
ENTITY_A {
|
|
string id PK
|
|
timestamp created_at
|
|
timestamp updated_at
|
|
string org_id FK
|
|
}
|
|
ENTITY_B {
|
|
string id PK
|
|
timestamp created_at
|
|
timestamp updated_at
|
|
string org_id FK
|
|
}
|
|
|
|
ORGANIZATIONS ||--o{ ENTITY_A : contains
|
|
ORGANIZATIONS ||--o{ ENTITY_B : contains
|
|
```
|
|
|
|
> 💡 **Note**: There are rare exceptions to the above star schema design. Consult with the maintainers before deviating from the above design.
|
|
|
|
All tables follow a consistent primary key pattern using a `id` column (referenced by the `types.Identifiable` struct) and include `created_at` and `updated_at` columns (referenced by the `types.TimeAuditable` struct) for audit purposes.
|
|
|
|
## How to write migrations?
|
|
|
|
For schema migrations, use the [SQLMigration](/pkg/sqlmigration/sqlmigration.go) interface and write the migration in the same package. When creating migrations, adhere to these guidelines:
|
|
|
|
- Do not implement **`ON CASCADE` foreign key constraints**. Deletion operations should be handled explicitly in application logic rather than delegated to the database.
|
|
- Do not **import types from the types package** in the `sqlmigration` package. Instead, define the required types within the migration package itself. This practice ensures migration stability as the core types evolve over time.
|
|
- Do not implement **`Down` migrations**. As the codebase matures, we may introduce this capability, but for now, the `Down` function should remain empty.
|
|
- Always write **idempotent** migrations. This means that if the migration is run multiple times, it should not cause an error.
|
|
- A migration which is **dependent on the underlying dialect** (sqlite, postgres, etc) should be written as part of the [SQLDialect](/pkg/sqlstore/sqlstore.go) interface. The implementation needs to go in the dialect specific package of the respective database.
|
|
|
|
## What should I remember?
|
|
|
|
- Use `BunDBCtx` and `RunInTxCtx` to access the database instance and execute transactions respectively.
|
|
- While designing new tables, ensure the consistency of `id`, `created_at`, `updated_at` and an `org_id` column with a foreign key constraint to the `organizations` table (unless the table serves as a transitive entity not directly associated with an organization but indirectly associated with one).
|
|
- Implement deletion logic in the application rather than relying on cascading deletes in the database.
|
|
- While writing migrations, adhere to the guidelines mentioned above.
|