字体
第(2/6)页
关灯
   存书签 书架管理 返回目录
r.item_id = scomvalue

    and outer.record_date = (select max(inner.record_date)

    from hist_data as inner

    where inner.item_id = outer.item_id

    and inner.record_date <= reference_date)

    考察这个查询的执行路径,我们发现:首先,内层查询与外层查询是有关联的(correlated), 因

    为内层查询参照了item_id的值,该值是由外层查询返回的当前记录一个字段。下面,先来分析

    外层查询。

    理论上,复合键中的字段顺序不会有太大影响,但实际上它们非常重要。如果我们误把主键定

    义为(record_date, item_id),而不是(item_id, record_date),前例的内层查询就非常依赖item_id

    字段的索引,否则无法高效地向下访问树状结构索引。但我们知道,额外增加一个索引的代价

    很高。

    外层查询找到了保存item_id 历史的各条记录,接着使用当前item_id 值逐次执行子查询。注

    意,内层查询只依赖item_id,这与外层查询处理的记录相同,这意味着我们执行相同的查询、

    返回相同的结果。优化器会注意到查询总是返回相同的值吗?无法确定。所以最好不要冒这个

    险。

    在使用关联子查询时,如果它处理不同的记录后总是返回相同的值,就没有意义了。所以,应

    该改用无关联子查询:

    select whatever

    from hist_data as outer

    where outer.item_id = scomvalue

    and outer.record_date = (select max(inner.record_date)

    from hist_data as inner

    where inner.item_id = scomvalue

    and inner.record_date <= reference_date)

    现在子查询的执行不需要访问表,只需访问主键索引就够了。

    个人习惯各有不同,但如果DBMS支持将“子查询的输出”与多个字段进行比较(这个特xìng不是

    所有产品都支持的),则应优先考虑基于主键比较:

    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 = scomvalue

    and inner.record_date <= reference_date

    group by inner.item_id)

    让子查询返回的字段,完全与复合主键的字段相符,有一定道理。如果必须返回“数据项值的列
上一页 目录 下一页