作为结构化查询语言 SQL 的语法相对于其他编程语言非常简单,常用的关键字也就几个,完成同样的统计功能,SQL 代码量较少,我们很容易将 SQL 代码映射到二维表中的数据,SQL 不同操作的代码其实就是对应着二维表的不断变换。由于SQL语句学习简单,表达能力强,上手容易的有点,所以在数据处理中SQL语句就成为了最通用的和最优先考虑处理方式。在大数据中 SQL 应用主要分两种:一种是周期性的统计任务,另一种是分析任务。
但是对于大数据处理来说,大量数据的复杂关联,使得SQL语句变得极为复杂并且团队中的每个人都可能有自己编写SQL的习惯,如果没有一套规范我们所编写的SQL语句肯定会令人别人难以阅读,甚至过了一段时间以后自己都无法理解。所以一套良好SQL编码规范是十分重要的。
希望这篇文章能作为你正在寻找的指导!
这里只针对数仓HIve来说,但是大部分是通用的,特殊情况我也会注明。
1、关键字使用大写
SQL关键字使用大写,表和列使用小写(oracle除外,oracle默认表、列就是大写)。在SQL函数都使用大写这样可以进行更好的区分,尽管这里有一些争议,但是我建议这样使用。
推荐写法
代码语言:javascript复制SELECT id, name FROM db.table
2、使用蛇形命名法
在大小写类型方面每个编程语言有自己的最佳命名规则:骆驼命名法、帕斯卡命名法、短横线命名法(html和css中常见)、蛇形命名法是最常见的几种命名规则
但是,当涉及到SQL时,蛇形命名法是最广泛使用的约定。
代码语言:javascript复制SELECT source,
COUNT(id) as nb_visit
FROM web_visit
GROUP BY source
尽管有些人喜欢使用大小写来区分库、表和列,但我还是建议使用蛇形命名法,尤其是在使用ORM框架进行基本的数据操作时。
3、使用别名提高可读性
添加别名是为明确表或列含义说明的方法。当表和列的名称没有意义时,请给它们加上别名,尤其是包含子查询的时候(Hive中子查询必须有别名),这样可以使得在阅读SQL时更加的方便。
代码语言:javascript复制SELECT customers.id,
customers.name,
customers.context_col1 as ip_address,
first_purchase.date as first_purchase_date
FROM company.customers
JOIN (
SELECT customer_id,
MIN(date) as date
FROM company.purchases
GROUP BY customer_id
) AS first_purchase
ON first_purchase.customer_id = customers.id
最后需要说明的是,别名一定要加上as,我通常用小写as来别名列,用大写AS来别名表。这样看起来会更加的方便,尤其是在搜索代码的时候。
4、使用缩进和空格
尽管这是一个基本原则,但它能让你的代码更具可读性。与使用python一样,应该对SQL代码进行缩进。
当使用了子查询或派生表时,这样可以使代码更加清晰,例如下面的语句
代码语言:javascript复制SELECT customers.id,
customers.name,
customers.age,
customers.gender,
customers.salary,
first_purchase.date
FROM company.customers
LEFT JOIN (
SELECT customer_id,
MIN(date) as date
FROM company.purchases
GROUP BY customer_id
) AS first_purchase
ON first_purchase.customer_id = customers.id
WHERE customers.age <= 30
如果你使用dbeaver或者vscode,他们的格式化功能会很好的完成这项工作,这就是我喜欢使用dbeaver访问hiveserver2做查询而不是直接使用hive-cli的重要的一个原因。
5、不要使用 SELECT *
无论是因为查询速度优化的原因,还是增加sql语句的可读性,都不要使用 * 作为查询的列名,因为查询的请求不清晰,隐藏了查询的意图。还有最主要的一点是,表可能会发生变化并影响SELECT *的结果,这个在做ETL的工作时候尤其重要。
6、使用ANSI-92的显式连接语法
一般的关系型数据库都支持FROM后指定多张表,并且在WHERE中指定连接关系的语法,相当于INNER JOIN,对于oracle还可以使用关键词( )指定是LEFT还是RIGHT JOIN,虽然这个在性能上没什么不同,但是却忽略了兼容性,尤其是在需要对SQL进行迁移时,例如从oracle ->hive、apache doris、clickhouse。所以这里我们还是建议使用ANSI-92的标准JOIN语法,虽然代码会多一些,但是JOIN子句将关系逻辑与过滤操作分离,提高了可读性和兼容性。
另外:“基于 WHERE 子句”的语法——也称被为 ANSI-89——是 ANSI-92 更旧的规范,这就是为什么一般数据库还支持他的原因,但是万一以后不支持了呢(虽然不太可能)?
7、使用公用表表达式 (CTE)
CTE 允许自定义和执行查询,其结果临时保存并在后续的查询中使用。大多数现代数据库都提供 CTE。
它像派生表一样工作,有两个优点:
- 使用 CTE 提高了查询的可读性
- CTE 定义一次,然后可以多次引用
使用 WITH ... AS 指令声明一个 CTE:
代码语言:javascript复制WITH my_cte AS
(
SELECT col1, col2 FROM table
)
SELECT * FROM my_cte
如果搜索有关Hive优化的文章,肯定会看到这个WITH操作,在Hive中CTE是保存在内存中的,可以提高执行速度。
8、一定要写注释……但不要太多
虽然编写良好且命名正确的代码是不应该需要注释的。但是阅读代码的人应该在看代码的同时就了解其逻辑和设计思路,这种情况下注释就变得有用。并且如果你不写注释,3个月前的代码你还记得思路吗?
注释是一个帮助我们回忆思路和逻辑的重要手段,但是我们也不能写太多,我们写的是注释,不是论文。
总结
SQL 数据分析、数据科学、数据工程甚至软件开发的基础之一:学习简单,表达能力强,上手容易是他最大的特点,并且到现在为止各种开发语言,开发框架的变更,SQL的地位却无人撼动,并且各种工具纷纷兼容(elasticsearch 6.3以后支持内置的SQL语法,你能相信一个搜索引擎可以支持使用简单SQL语句查询)。
以上这些内容可能作为基础开发的时候没有意识到这一点,但是当你与团队一起工作或者成为技术负责人时,你就会意识到没有一套 SQL 代码规范将成为一种负担。
在本文中总结的这些SQL规范都是基于我个人意见,这里可能有些是有争议的,但是我希望从这里能给你一些不同的启发。希望它能帮你将 SQL 质量提升到一个新的水平!