`
septem
  • 浏览: 54458 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

SQL语言艺术(六)锦囊妙计:认识经典SQL模式

    博客分类:
  • sql
阅读更多
本章讨论存取经过适当规范化的数据时,遇到的9种最经典的情况

小结果集,源表较少,查询条件直接针对源表

对于典型的OLTP应用,多为返回小结果集的查询。如果过滤条件直接针对源表,我们必须保证这些过滤条件高效,对于重要的字段,考虑加上索引。如果涉及连接多表的情况,需要优化连接顺序,尽快过滤不符合条件的记录。如果统计数据足够精确地反映了表的内容,优化器有可能对连接顺序做出适当选择

在使用索引字段的时候要注意,函数或者隐式转换会导致索引失效。在确定重要字段有索引的情况下,还必须如果是非唯一性索引或者基于唯一性索引的范围扫描,还需要考虑聚集索引与分区,物理数据的顺序是否与索引一致,对性能影响很大

小结果集,查询条件涉及源表之外的表

我们想要的数据来自一个表,但查询条件是针对其它表的,且不需要从这些表返回任何数据。就像之前讨论过的订单的例子,这类查询可以使用连接,加上distinct去除结果中的重复记录。但较好的方式是使用子查询,在没有其它条件的情况下,优先考虑非关联子查询,因为关联子查询需要扫描源表

小结果集,多个宽泛条件,结果集取交集

分别使用各个条件时,会产生大量数据,但各个条件的交集是小结果集。使用正规连接,关联子查询,还是非关联子查询,要根据不同条件的过滤能力和已存在哪些索引而定

小结果集,一个源表,查询条件宽泛且涉及多个源表之外的表

如果查询条件可选择性较差,优化器可能会选择忽略它们,先访问关联的所有小型,再对其它表运用过滤条件。将提供的查询条件推迟执行,不利于减少要处理的数据量。这时我们必须迫使DBMS依我们所需的方式执行查询。多数SQL方言都支持优化器的提示(hint),但这种方法会随着未来的环境,数据量,硬件等因素的变化而变得不适用。更优雅的方法是在from子句中采用嵌套查询,在数值表达式中建议连接关系。通常没有必要采用非常具体的的方式和难以理解的提示,提供正确的最初指导就可使优化器找到正确的执行路径。混乱的查询会让优化器困惑,结构清晰的查询及合理的连接建议,通常足以帮助优化器提升性能

大结果集

如果查询返回几万条记录,那么使用索引是没有意义的,借助hash join或者merge join进行全表扫描是合适的。我们必须扫描数据返回比例最高的表,它违背了尽快去除不必要数据这一原则,但一旦扫描结束应立即重新贯彻该原则

在大结果集的情况下,每条记录的处理都必须小心,避免性能不佳的自定义函数的调用,另外处理大量记录时,关联查询是性能杀手。录一个查询包含多个子查询时,必须让它们操作各不相同的数据子集,避免子查询相互依赖,到查询执行的最后阶段,多个子查询得到的不同数据集经过hash join或者集合操作得到结果集

结果集来自基于一个表的自连接

自连接的情况除了一般规则之外,比如保证索引高效,应该尽量通过一次处理收集所有感兴趣的记录,再使用诸如case语句等结构分别显示记录。通常当需要查找和最小,最大,最早或最近的值相关的数据时,首先必须找到这些值本身,接下来用这些值作为第二遍扫描的搜索条件。而以滑动窗口(sliding window)为基础的OLAP函数,可以将两遍扫描合而为一。当多个选取条件作用于同一个表的不同记录时,可以使用基于滑动窗口工作的函数

结果集以聚合函数为基础获得

此时结果集大小取决于group by的字段基数而不是查询条件的精确性。实际上最让人感兴趣的SQL聚合使用技巧,不是显式的sum或avg,而是如何将过程性处理转化为以聚合为基础的纯SQL替代方案。优秀SQL编程的困难,多半在于解决问题的方式,不要将一个问题转换成对数据库的一系列查询,而是转换成少数查询。程序中大量中间变量保存从数据库读出的值,然后根据变量进行简单判断,最后再把它们作为其它查询的输入,这样做是错误的。糟糕的SQL编程有个显著特点,就是SQL之外存在大量代码,以循环的方式对返回数据进行加,减,乘,除之类的处理,这里的工作应该交给SQL的聚合函数

比如以下的查询语句:
select shipment_id
    from shipments
    where shipment_id not in (select shipment_id
                              from orders
                              where order_complete = 'N')

可以转化为聚合函数:
select shipment_id
    from orders
    group by shipment_id
    having sum(case when order_complete = 'N' then 1
                                              else 0
               end) =0

甚至可以不进行任何转换:
select shipment_id
    from orders
    group by shipment_id
    having min(order_complete) = 'Y'


聚合操作的数据应尽量少,把条件放到where子句中,能让多余的记录尽早被过滤掉,因而更高效

结果集通过简单搜索或基于日期的范围搜索获得

如果历史数据较少,那么各项ID的可选择性很高,比如:
select whatever
    from hist_data as outer
    where (outer.item_id, outer.record_date) in
                              (select inner.item_id, max(inner.record_date)
                               from hist_data as inner
                               where inner.item_id = somevalue
                                 and inner.record_date <= reference_date
                               group by inner.item_id)

OLAP在查询特定日期某数据项的值时也同样有用,但OLAP属于SQL的非关系层

对于大量历史数据的情况下,难度在于排序,对大量数据的排序代价是很高的。而且排序是非关系操作,降低非关系层厚度的唯一方法就是在关系层多做一些工作,增加过滤条件的数量。此时,针对所需数据更精确地归类日期以缩小范围,便非常重要。如果我们把数据控制在可管理的大小,就相当于回到了少量历史记录的情况。如果无法同时指定上限和下限,我们的唯一希望就是根据数据项分区,在单一分区上操作,这比较接近大结果集的情况

结果集和别的数据存在与否有关

对于识别例外的需求,最常用的解决方案有两个:not in搭配非关联子查询,或者not exists搭配关联子查询。在子查询出现在高效搜索条件之后,使用not exists是对的,但当子查询是唯一条件时,使用not in比较好

使用count(*)测试某些数据是否存在是个糟糕的主意,为此DBMS必须搜索并找出所有相符的记录,此时应该使用exists,它会在遇到第一个相符的数据时就停止。

集合操作符的重大优点是彻底打破了子查询强加的时间限制。当存在关联子查询时,就必须执行外层查询,接着对所有通过过滤条件的记录执行内层查询。外层查询和内层查询相互依赖,因为外层查询会把数据传递给内层查询。非关联子查询必须先完成内层查询之后,外层查询才能介入。相比之下,使用集合操作符union, intersect或except时,查询中的这些组成部分不会彼此依赖,从而不同部分的查询可以并行执行,最后把不完整的结果集组合起来,这就是分而治之

另一个表达非存在性的方法是使用外连接(out join),通过检查连接表的字段值是否为null找出它们。数据集可以通过各种技巧进行比较,但一般而言,使用外连接和子集合操作符更高效
3
0
分享到:
评论

相关推荐

    SQL语言艺术pdf

    第6章,锦囊妙计:认识经典 SQL模式包括经典的 SQL模式、以及如何处理第7章,变换战术:处理层次结构 说明如何处理层次数据 第8章,孰优孰劣:认识困难,处理困难 指出如何认识和处理比较棘手的情况 第9章,多条...

    SQL语言艺术(pdf格式)

    第6章,锦囊妙计:认识经典SQL模式 包括经典的SQL模式、以及如何处理 第7章,变换战术:处理层次结构 说明如何处理层次数据 第8章,孰优孰劣:认识困难,处理困难 指出如何认识和处理比较棘手的情况 第9章,多条战线...

    SQL语言艺术

    6 锦囊妙计:认识经典SQL模式 小结果集,直接条件 小结果集,间接条件 多个宽泛条件的交集 多个间接宽泛条件的交集 大结果集 基于一个表的自连接 通过聚合获得结果集 基于日期的简单搜索或范围搜索 结果集和别的数据...

    基础电子中的SQL语言艺术

    第六章“锦囊妙计:认识经典SQL模式”涵盖了常见的SQL模式及其处理方式。第七章“变换战术:处理层次结构”讲述了如何处理层次型数据。第八章“孰优孰劣:认识困难,处理困难”面对复杂的性能问题提出了应对策略。第...

    87 数字化转型破解企业数字化增长难题的锦囊妙计:知己知彼与和而不同.docx

    这要求企业对自身所在行业有清晰的认识,明确数字化转型的目标,以适应数字经济环境。例如,互联网行业在数字化转型上已有较成熟的基础,而制造业可能需要更长的时间来适应和转变。即使是同一行业的企业,由于规模、...

    【数字化转型】破解企业数字化增长难题的锦囊妙计:知己知彼与和而不同.pdf

    数字化转型并非单纯的技术升级,而是对商业模式、运营模式的根本性重塑。市场对反应速度和个性化服务的要求日益提高,企业需要通过数据分析和挖掘,理解并预测消费者行为,以提供更精准的服务。这要求企业具备强大的...

    【数字化转型】破解企业数字化增长难题的锦囊妙计:知己知彼与和而不同 (2).pdf

    数字化转型并非简单叠加新技术,而是对整个商业模式、运营模式的根本性变革。在数字市场中,数据成为驱动因素,消费者需求多元化,要求企业具备快速响应的能力。因此,企业需要具备强大的数据分析能力,以挖掘消费者...

    【数字化转型】破解企业数字化增长难题的锦囊妙计:知己知彼与和而不同 (2).docx

    以制造业为例,某些制造业企业可能刚开始数字化转型,目标可能是提升制造效率或实现智能制造,而互联网企业可能已经建立了以科技和数据为核心的业务模式。在转型前,企业需要全面评估自身的业务流程、技术基础和人才...

    锦囊妙计三十六.pptx

    【服务行销锦囊】是针对保险行业销售与客户服务策略的一种综合指导,旨在提升客户满意度,建立长期稳定的客户关系,并通过优质服务实现双赢。以下是这些锦囊中的关键知识点: 1. **感谢投保函**:在客户完成投保...

    面试锦囊妙计经典java asp.net php 面试题目

    Java是一种广泛使用的面向对象的编程语言,以其“一次编写,到处运行”的特性而闻名。面试中可能会考察以下几个核心概念: 1. **Java基础**:包括变量、数据类型、运算符、控制结构(如if-else,switch,for,while...

    程序员入职的锦囊妙计

    程序员入职的锦囊妙计

    Java设计模式经典搞笑珍藏版

    ### Java设计模式经典搞笑珍藏版 #### 一、引言 《Java设计模式经典搞笑珍藏版》这本书以一种轻松幽默的方式介绍了23种经典的设计模式及其在Java中的应用。设计模式是一种软件工程领域中非常重要的概念,它提供了...

    Java设计模式之禅

    《Java设计模式之禅》是一本深入浅出讲解设计模式的书籍,书中不仅包含23种经典设计模式的案例,还详细介绍了设计模式背后的思想和原则,适合初学者以及对设计模式有一定了解的程序员阅读。本书旨在帮助读者理解如何...

    《程序员入职锦囊妙计》 pdf

    他以幽默风趣、通俗易懂的语言,从不同角度深入剖析了软件开发职场的“规则”,并且在书中对如何判断公司是否适合自己、如何与领导和同事打交道、如何争取项目机会、如何看待加班、如何积累管理经验以及升职应做的...

    名师指点高考数学复习方法的六大锦囊妙计.pdf

    对于难题,要掌握文字、符号和图形三种语言之间的转换,这是解题的关键。 复习阶段,加倍递减训练法是一种有效的心理调适和技能提升方法,但需在专业人士指导下进行。此外,考前应避免接触新题,而是重做过去做错的...

    项目管理的20条锦囊妙计

    在项目管理中,确保项目的顺利进行需要一系列精心策划和执行的策略。以下是一些关键的知识点,涵盖了...这些锦囊妙计提供了全面的项目管理指导,项目经理应灵活运用,结合实际情况调整策略,以确保项目的高效和成功。

    java设计模式---诙谐易懂版

    例如,代理模式(Proxy Pattern)、单例模式(Singleton Pattern)、工厂方法模式(Factory Method Pattern)、抽象工厂模式(Abstract Factory Pattern)、适配器模式(Adapter Pattern)、模板方法模式(Template ...

Global site tag (gtag.js) - Google Analytics