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

122 lines
4.2 KiB
Markdown
Raw Normal View History

2022-07-31 16:42:53 +00:00
# SQL
2022-11-20 09:35:49 +00:00
Previously in my fresher software developer time, I rarely write SQL, I always use ORM to wrap SQL.
2022-07-31 16:42:53 +00:00
But time past and too much abstraction bites me.
2022-11-20 09:35:49 +00:00
So I decide to only write SQL from now as much as possible, no more ORM for me.
2022-07-31 16:42:53 +00:00
But if there is any cool ORM for Go, I guess I try.
This guide is not kind of guide which cover all cases.
Just my little tricks when I work with SQL.
2022-11-20 09:35:49 +00:00
## Stay away from database unique id
2022-09-06 17:10:02 +00:00
Use UUID instead.
2022-11-20 09:35:49 +00:00
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
2022-11-20 09:35:49 +00:00
Stay away from all kind of database timestamp (MySQL timestmap, SQLite timestamp, ...)
2022-07-31 16:42:53 +00:00
Just use int64 then pass the timestamp in service layer not database layer.
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-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
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.
I always use MySQL json data type for extra field.
2023-04-08 10:10:10 +00:00
JSON data type also used for dumping request, response data.
2022-11-20 09:35:49 +00:00
## Use index!!!
2022-07-31 16:42:53 +00:00
You should use index for faster query, but not too much.
Don't create index for every fields in table.
Choose wisely!
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);
```
If create index inside `CREATE TABLE`, [prefer `INDEX` to `KEY`](https://stackoverflow.com/a/1401615):
```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)
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`
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.
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!!!
Plase read docs about online ddl operations before do anything online (keep database running the same time update it, for example create index, ...)
- [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)
## Tools
- 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 :)
## 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)