大部分公司对于SQL 的优化都是在出了问题后来优化,上了线后在去看慢查询语句。大部分业界99%是基于这样的做法,如同把眼看你喝完慢性毒药,发病后再给你调理,最终留下的一个个不解的病根。
到底SQL 优化应该从哪里开始,是应该从需求的阶段开始而不是病了在去优化,这里面第一个该介入的是开发人员,在理解需求的时候就对数据表的设计有一定的规划,而不是whatever , please let DBA do it ,have fun !
如果你是DBA 在那堆人给你审核SQL的需求时,就在给你机会纠正他们的错误,而DBA需要的是理解这个设计中的业务,在理解业务的同时来看看设计表有没有问题,我们当下DBA 的审核和 屠宰场电死猪一样 没有什么意义,只需要click "OK" and then,猪已经死了,死在你手里了, it's done.
举例,以电商的客户信息为例,我可以将表设计成一个如下图
user_info (表名),开发一般会设计成这样
account_id
first_name
last_name
home_phone
work_phone
cell_phone
也可以设计成 下面这样
user_info(表名)
phone_info
account_id phone_id
email account_id
first_name phone_type
last_name phone_number
或者下面这样
user_info(表名)
phone_info
account_id phone_id
email account_id
first_name home_phone
last_name work_phone
cell_phone
到底上面的3中设计方式那个更好,看需求,对看需求
如果电话号码在需求的维度中不会作为一个单独的信息被搜索出来,而是用户提取信息时的附加品, 那设计成一张表是最好的。
而如果电话号不是一个附加品,会通过他来统计电话的类型并且经常获取电话中某一种类型,那第二种设计的方式会更好,反之用户中的电话信息都会在查询中出现,那么第三种会更好。
如需求在延伸,用户电话号码是默认的,是第一位的,是常用沟通的,可以在设置一个字段,默认或首选,用 1 0 标识的整形都表达都可以。
上面做的一切都是为了你在撰写SQL语句的时候,能最大化的避免撰写出难以优化的语句,并在同等优化下,表能够承载更多的数据。
实际上SQL的优化是一个“玄学的问题”, 一个SQL运行的速度与开发人员对业务的理解有关,与SQL 所在的数据库类型有关, 与SQL所在的数据库硬件有关,与所在数据库所调整的参数有关,还与SQL 运行的频率,以及数据库本身所承载的总的TPS QPS 有关,还与数据量有关, 这一切加载在一起,才是一个SQL 运行效率的快慢可能性的存在。
此时此刻,你还在为一个索引解决了SQL 的快慢问题而感到“高兴” OMG。
回到文中的主题POSTGRESQL , 这里并不是要讲怎么从业务的角度分析你的表该怎么设计,而是在讨论如果你的数据库系统是建立与 POSTGRESQL 之上的该怎么通过 POSTGRESQL 的方式方法来承接你的表, 以及可能通过什么手段来优化这些查询,仅此而已。因为我们还需要回到实际的情况,大部分99%的企业还是要让你用最后一招来拯救已经千疮百孔的系统。
所以就必须具备第一种数据库库SQL 优化的能力,这里编写数据库查询不同于使用命令式语言编写应用程序代码。SQL是一种声明性语言,这意味着我们指定所需的结果,不指定执行路径。由于产生相同结果的两个查询可能以不同的方式执行,利用不同的资源和花费不同的时间,因此优化和“像数据库一样思考”是SQL开发的核心部分。
那么POSTGRESQL 的SQL 优化应该从那些层面开始,下面罗列了一些对于SQL 优化 DBA 需要了解和掌握的知识
1 SQL 编译与优化引擎和执行
2 数据的访问逻辑数据的存储结构
3 full scan index scan 的不同
4 Nested loops , hash , sort merge , 之间的不同
5 执行计划如何评判自己是对的
6 索引,复合索引,唯一索引,部分索引 ,索引与 JOIN 之间的关系
7 怎么去在查询中对索引正确选择
8 对于大SQL 如何进行写法优化,视图,物化事务到底那个更好
9 全文索引与全文查询
10 如何提升在POSTGRESQL 数据插入的性能(upsert)
后面会分别写写这些东西,同时也有同学问关于 postgresql一些语句的写法的问题,例如 upsert 到底应该不应该用等等。