首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

多个宽泛条件的交集

Small Intersection of Broad Criteria

本节讨论对多个宽泛条件取交集获得较小结果集的情况。在分别使用各个条件时,会产生大型数据集,但最终各个大型数据集的交集却是小结果集。

继续上一节的例子。如果“判断订购的商品是否存在”可选择性较差,就必须考虑其他条件(否则结果集就不是小结果集)。在这种情况下,使用正规连接、关联子查询,还是非关联子查询,要根据不同条件的过滤能力和已存在哪些索引而定。

例如,由于不太畅销,我们不再检索订购蝙蝠车的人,而是查找上周六购买某种肥皂的客户。此时,我们的查询语句为:

select distinct orders.custid

from orders

     join orderdetail

        on (orderdetail.ordid = orders.ordid)

     join articles

        on (articles.artid = orderdetail.artid)

where articles.artname = 'SOAP'

  and <selective criterion on the date in the orders table>

这个处理流程很合逻辑,该逻辑和商品具有高可选择性时相反:先取得商品,再取得包含商品的明细订单,最后处理订单。对目前讨论的肥皂订单的情况而言,我们应该先取得在较短期间内下的少量订单,再检查哪些订单涉及肥皂。从实践角度来看,我们将使用完全不同的索引:第一个例子需要orderdetail表的商品名称、商品ID这两个字段上的索引,以及orders表的主键orderid上的索引;而此肥皂订单的例子需要orders表日期字段的索引、orderdetail表的订单ID字段的索引,以及articles表的主键orderid上的索引。当然,我们首先假设索引对上述两例都是最佳方式。

要知道哪些客户在上星期六买了肥皂,最明显而自然的选择是使用关联子查询:

select distinct orders.custid

from orders

where <selective criterion on the date in the orders table>

  and exists (select 1

              from orderdetail

                  join articles

                    on (articles.artid = orderdetail.artid)

                where articles.artname = 'SOAP'

                  and orderdetails.ordid = orders.ordid)

在这个方法中,为了使关联子查询速度较快,需要orderdetail表的 ordid字段上有索引(就可以通过主键artid取得商品,无需其他索引)。

第3章已提到,事务处理型数据库(transactional database)的索引是种奢侈,因为它处在经常更改的环境中,维护的成本很高。于是选择“次佳”解决方案:当表orderdetail 上的索引并不重要,而且也有充足理由不再另建索引时,我们考虑以下方式:

select distinct orders.custid

from orders,

     (select orderdetails.ordid

      from orderdetail,

           articles

      where articles.artid = orderdetail.artid

        and articles.artname = 'SOAP') as sub_q

where sub_q.ordid = orders.ordid

  and <selective criterion on the date in the orders table>

这第二个方法对索引的要求有所不同:如果商品数量不超过数百万项,即使artname字段上没有索引,基于商品名称条件的查询性能也不错。表orderdetail的artid字段可能也不需索引:如果商品很畅销,出现在许多订单中,则表orderdetail和articles之间的连接通过哈希或合并连接(merge join)更高效,而artid字段上的索引会引起嵌套的循环。与第一种方法相比,第二种方法属于索引较少的解决方案。一方面,我们无法承受为表的每个字段建立索引;另一方面,应用中都有一些“次要的”查询,它们不太重要,对响应时间要求也不苛刻,索引较少的解决方案完全满足它们的要求。

总结:为现存的查询增加搜索条件,可能彻底改变先前的构想:修改过的查询成了新查询。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论