posts-go/posts/2022-07-31-sql.md

151 lines
4.7 KiB
Markdown
Raw Normal View History

2022-07-31 16:42:53 +00:00
# SQL
2023-08-05 18:56:25 +00:00
Previously in my fresher software developer time, I rarely write SQL, I always
use ORM to wrap SQL. But time past and too much abstraction bites me. So I
decide to only write SQL from now as much as possible, no more ORM for me. But
if there is any cool ORM for Go, I guess I try.
2022-07-31 16:42:53 +00:00
2023-08-05 18:56:25 +00:00
This guide is not kind of guide which cover all cases. Just my little tricks
when I work with SQL.
2022-07-31 16:42:53 +00:00
2022-11-20 09:35:49 +00:00
## Stay away from database unique id
2022-09-06 17:10:02 +00:00
2023-08-05 18:56:25 +00:00
Use UUID instead. If you can, and you should, choose UUID type which can be
sortable.
2022-09-06 17:10:02 +00:00
2022-11-20 09:35:49 +00:00
## Stay away from database timestamp
2022-07-31 16:42:53 +00:00
2023-08-05 18:56:25 +00:00
Stay away from all kind of database timestamp (MySQL timestmap, SQLite
timestamp, ...) Just use int64 then pass the timestamp in service layer not
database layer.
2022-07-31 16:42:53 +00:00
2023-08-05 18:56:25 +00:00
Why? Because time and date and location are too much complex to handle. In my
business, I use timestamp in milliseconds. Then I save timestamp as int64 value
to database. Each time I get timestamp from database, I parse to time struct in
Go with location or format I want. No more hassle!
2022-07-31 16:42:53 +00:00
2022-11-20 09:35:49 +00:00
It looks like this:
```txt
[Business] time, data -> convert to unix timestamp milliseconds -> [Database] int64
```
2023-04-04 10:25:22 +00:00
## Extra field for extra things
2023-08-05 18:56:25 +00:00
Create new column in database is scary, so I suggest avoid it if you can. How to
avoid, first design table with extra field. It is black hole, put everything in
there if you want.
2023-04-04 10:25:22 +00:00
I always use MySQL json data type for extra field.
2024-01-03 10:17:15 +00:00
JSON data type is also useful for dumping request, response data.
- [For MySQL 5.7](https://dev.mysql.com/doc/refman/5.7/en/json.html)
- [For MySQL 8.0](https://dev.mysql.com/doc/refman/8.0/en/json.html)
Use `JSON_EXTRACT(col, '$.key') IS NULL` to check json field exist or not.
2023-04-08 10:10:10 +00:00
2022-11-20 09:35:49 +00:00
## Use index!!!
2022-07-31 16:42:53 +00:00
2023-08-05 18:56:25 +00:00
You should use index for faster query, but not too much. Don't create index for
every fields in table. Choose wisely!
2022-07-31 16:42:53 +00:00
For example, create index in MySQL:
```sql
2023-06-15 19:31:21 +00:00
CREATE INDEX idx_user_id
ON user_upload (user_id);
```
2023-08-05 18:56:25 +00:00
If create index inside `CREATE TABLE`,
[prefer `INDEX` to `KEY`](https://stackoverflow.com/a/1401615):
2023-06-15 19:31:21 +00:00
```sql
CREATE TABLE user_upload
(
id int(11) NOT NULL,
user_id int(11) NULL DEFAULT NULL,
PRIMARY KEY (id),
INDEX idx_user_id (user_id)
);
2022-07-31 16:42:53 +00:00
```
2023-04-17 10:14:54 +00:00
Use `EXPLAIN` to check if index is used or not:
- [For MySQL 5.7](https://dev.mysql.com/doc/refman/5.7/en/explain-output.html)
- [For MySQL 8.0](https://dev.mysql.com/doc/refman/8.0/en/explain-output.html)
2023-10-05 06:39:09 +00:00
## Be careful with UTF-8
TLDR with MySQL:
```sql
CREATE TABLE ekyc_approved
(
id varchar(30) NOT NULL,
PRIMARY KEY (id),
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
```
2022-11-20 09:35:49 +00:00
## Be careful with NULL
2022-09-06 17:10:02 +00:00
If compare with field which can be NULL, remember to check NULL for safety.
```sql
-- field_something can be NULL
2022-11-20 09:35:49 +00:00
-- Bad
2022-09-06 17:10:02 +00:00
SELECT *
FROM table
WHERE field_something != 1
2022-11-20 09:35:49 +00:00
-- Good
2022-09-06 17:10:02 +00:00
SELECT *
FROM table
WHERE (field_something IS NULL OR field_something != 1)
```
2022-11-20 09:35:49 +00:00
Need clarify why this happpen? Idk :(
## `VARCHAR` or `TEXT`
2023-08-05 18:56:25 +00:00
Prefer `VARCHAR` if you need to query and of course use index, and make sure
size of value will never hit the limit. Prefer `TEXT` if you don't care, just
want to store something.
2022-11-20 09:35:49 +00:00
2023-06-15 19:31:21 +00:00
## `LIMIT`
Prefer `LIMIT 10 OFFSET 5` to `LIMIT 5, 10` to avoid misunderstanding.
2022-11-20 09:35:49 +00:00
## Be super careful when migrate, update database on production and online!!!
2023-08-05 18:56:25 +00:00
Plase read docs about online ddl operations before do anything online (keep
database running the same time update it, for example create index, ...)
2022-11-20 09:35:49 +00:00
2023-08-05 18:56:25 +00:00
- [For MySQL 5.7](https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html),
[Limitations](https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-limitations.html)
- [For MySQL 8.0](https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html),
[Limitations](https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-limitations.html)
2022-11-20 09:35:49 +00:00
2023-08-17 09:40:38 +00:00
## Heathcheck
Use `SELECT 1` to check if database failed yet.
2022-11-20 09:35:49 +00:00
## Tools
2023-08-05 18:56:25 +00:00
- Use [sqlfluff/sqlfluff](https://github.com/sqlfluff/sqlfluff) to check your
SQL.
- Use [k1LoW/tbls](https://github.com/k1LoW/tbls) to grasp your database reality
:)
2022-11-20 09:35:49 +00:00
## Thanks
2022-07-31 16:42:53 +00:00
- [Use The Index, Luke](https://use-the-index-luke.com/)
- [Essential elements of high performance applications: SQL indexes](https://www.foxhound.systems/blog/essential-elements-of-high-performance-sql-indexes/)
- [Things You Should Know About Databases](https://architecturenotes.co/things-you-should-know-about-databases/)
2023-04-08 10:10:10 +00:00
- [When to use JSON data type in database schema design?](https://shekhargulati.com/2022/01/08/when-to-use-json-data-type-in-database-schema-design/)
- [My Notes on GitLab Postgres Schema Design](https://shekhargulati.com/2022/07/08/my-notes-on-gitlabs-postgres-schema-design/)
2023-04-17 10:14:54 +00:00
- [How to read MySQL EXPLAINs](https://planetscale.com/blog/how-read-mysql-explains)
2023-08-17 09:40:38 +00:00
- [Honest health checks that hit the database](https://brandur.org/fragments/database-health-check)