代码之家  ›  专栏  ›  技术社区  ›  Joe R.

继续-在查询完成前查看第一行

  •  2
  • Joe R.  · 技术社区  · 15 年前

    我已经确定了我的用户通常使用的查询结构。对于我来说,创建复合索引来支持这些构造并提供第一行功能是否有意义?

    如果我从SE迁移到IDS,我将失去使用C-ISAM调用编写低级函数的能力,但会获得第一行以及其他优点,如:索引扫描的设置读取(onconfig use_[ko]batchedread)、优化器指令、并行查询等。


    评论中的信息

    当铺生产表的查询依据:customer.name char(30),使用通配符(las) 苏尔 f*要查找姓氏、名字)或通过Pawns.Ticket_number int查询。客户和Pawns的连接方式为:customer.name=Pawns.name,not customer.serial=Pawns.fk。trx日期大于1年的当铺将移动到另一个硬盘上的另一个数据库中的历史表(>500k nrows)。历史索引按trx_日期降序排列。这就是即席复合查询构造发挥作用的地方。

    一旦找到客户的典当交易,当客户进行Intrest或赎回Pymt时,该行将更新。如果客户在90天内不制作Pymt,用户将手动更新将要没收的典当。当铺。当客户赎回当铺或因缺少Pymt而没收当铺时,状态变为不活动。当他们的trx日期超过1年时,不活动的人会从当铺表移到历史表中,因此在这个应用程序中不会发生大规模更新。当铺每天早上开业前都会运行这个程序。

    {ISQL 2.10.06E (SE-DOS16M protected mode) pawns table optimization - 
     once-daily, before start of business, procedure}
    
     unload to "U:\UNL\ACTIVES.UNL"
        select * from pawns where pawns.status = "A"
      order by pawns.cust_name, pawns.trx_date;
    
     unload to "U:\UNL\INACTIVE.UNL"
        select * from pawns
         where pawns.status <> "A"
           and pawns.trx_date >= (today - 365)
      order by pawns.cust_name, pawns.trx_date desc;
    
     unload to "U:\UNL\HISTORIC.UNL"
        select * from pawns
         where pawns.status <> "A"
           and pawns.trx_date < (today - 365)
      order by pawns.trx_date desc;
    
     drop table pawns;
    
     create table pawns
     (
         trx_num serial,
         cust_name char(30),
         status char(1),
         trx_date date,
     . . . ) in "S:\PAWNSHOP.DBS\PAWNS";
    
     load from "U:\UNL\ACTIVES.UNL" insert into pawns;         {500:600 nrows avg.}
     load from "U:\UNL\INACTIVE.UNL" insert into pawns;        {6500:7000 nrows avg.}
     load from "U:\UNL\HISTORIC.UNL" insert into dss:historic; {>500K nrows}
    
     create cluster index pa_cust_idx on pawns (cust_name);
    
     {this groups each customers pawns together, actives in
      oldest trx_date order first, then inactive pawns within the last year in most 
      recent trx_date order. inactives older than 1 year are loaded into historic 
      table in a separate database, on a separate hard disk. historic table 
      optimization is done on a weekly basis for DSS queries.}
    
     create unique index pa_trx_num_idx on pawns (trx_num);
     create index pa_trx_date_idx on pawns (trx_date);
     create index pa_status_idx on pawns (status);
    
     {grant statements...}
    
     update statistics;
    
    1 回复  |  直到 14 年前
        1
  •  1
  •   Jonathan Leffler    15 年前

    没有一个简单的“是/否”答案——这是一种平衡行为,因为存在许多性能问题。

    与指数相关的两个主要成本必须与收益平衡。

    1. 在表中添加、删除和修改行时,必须维护索引。成本不高,但也不能忽略不计。
    2. 索引占用磁盘空间。

    当查询有更多的索引时,还有一个很小的开销,因为查询被优化了。

    好的索引的主要好处是,当索引可以很好地使用时,在选择数据方面的性能大大提高。

    如果您的表不是非常易变的,并且经常使用索引可以帮助的条件进行搜索,那么创建复合索引可能是有意义的,假设磁盘空间不是问题。

    如果您的表非常不稳定,或者某个特定的索引很少被使用(但在使用它的少数情况下是有益的),那么您可能应该权衡一个较慢查询的几乎一次性的成本与存储和维护索引的成本,以备少数情况下使用它。

    有一本关于索引设计主题的好书: Relational Database Index Design and the Optimizers 由Lahdenm_¥ki和Leach(它也相当昂贵)。


    在最近的评论中,弗兰克说:

    [我]找一些东西。正如前面所说,最简单的事情就是允许Informix在拥有行之后开始返回行。(默认情况下,甲骨文是这样做的。)弗兰克所要求的更大的情况与谷歌的情况类似。好吧,这真的可以追溯到AltaVista和90年代,当时谈论的是网络上的搜索索引。这样做的目的是,您可以快速搜索,在报告搜索中返回的行数的同时提取前n个内容。(好像谷歌报告的数字是准确的。)

    弗兰克的这一附加评论在这个问题的背景下更有意义,因为这是一个延续。

    显然,除非SQL语句强制Informix进行排序,否则一旦有了结果,它就会立即提供结果;总是这样。这个 FIRST_ROWS 优化提示向IDS表明,如果它有两个查询计划可供选择,其中一个计划将使它比另一个计划更快地生成第一行,那么它应该更喜欢快速生成第一行的计划,即使它的总体成本比另一个计划更高。即使在没有提示的情况下,IDS仍然试图尽可能快地提供数据——它也试图尽可能高效地提供数据。

    准备好查询后,您将得到可能返回多少行的估计值—您可以将其用作指示器(一些、相当多、非常多)。另外,您可以快速独立地发现正在搜索的主表中的行数。鉴于此元数据,您当然可以使用滚动光标技术在数据库中为您提供一个后备存储,其中包含您感兴趣的行的主键值。在任何时候,您都可以为一组有趣的行加载一个带有显示数据的数组,以便向用户显示。根据用户的请求,您可以安排显示另一个充满信息的页面。在程序的某个时刻,您会发现您已经到达滚动光标中数据的末尾。很明显,如果你最后一个抓到,你就强迫它发生。如果您只需要再做一些提取nexts,那么您最终会得到一个未找到的条件。

    从80年代后期开始,Informix(ID及其先前的化身,在线、turbo、se和i4gl)就可以实现所有这一切。第一行优化是最新的;它仍然只是优化器的一个提示,通常对优化器所做的工作没有什么影响。