需要帮助为informix表构建良好的索引

时间:2017-11-09 09:52:30

标签: sql indexing informix

我有一个Informix 11.7服务器,其数据库表有3000万行。 表模式如下:

CREATE TABLE ppd (
    datum DATE,
    obrabot INTEGER,
    rb_obr INTEGER,
    blag_sif_transakcija INTEGER,
    tip_transakcija CHAR(20),
    tabela_kod CHAR(5),
    vrska_sif_transakcija INTEGER,
    ekspozitura CHAR(3),
    valuta CHAR(3),
    iznos_p DECIMAL(20,2),
    iznos_d DECIMAL(20,2),
    smetka CHAR(15),
    podsmetka CHAR(9),
    client_id CHAR(13),
    client_tip CHAR(1),
    client_naziv CHAR(100),
    adresa CHAR(100),
    edb CHAR(13),
    pasos CHAR(20),
    maticen_broj CHAR(20),
    vid_rabota CHAR(2),
    smetka_primac CHAR(15),
    naziv_primac CHAR(100),
    broj_primac CHAR(20),
    smetka_davac CHAR(15),
    naziv_davac CHAR(100),
    broj_davac CHAR(20),
    edb_fl CHAR(13),
    sifra_plakanje CHAR(6),
    namena CHAR(100),
    vo_valuta CHAR(3),
    vo_iznos DECIMAL(20,2),
    datum_vreme DATETIME YEAR TO SECOND,
    operator CHAR(3),
    flag INTEGER,
    potpisnik CHAR(10)
);

在这个表上有6个索引,它们彼此非常相似,我认为它们写错了,这就是为什么在这个表上运行查询很慢的原因。对于19000行,需要30分钟。 这是索引的样子:

CREATE INDEX ix_ppd_1 ON ppd (datum,operator,client_id,obrabot);
CREATE INDEX ix_ppd_2 ON ppd (datum,operator,edb,obrabot);
CREATE INDEX ix_ppd_3 ON ppd (datum,operator,maticen_broj,obrabot);
CREATE INDEX ix_ppd_4 ON ppd (datum,operator,rb_obr,obrabot);
CREATE INDEX ix_ppd_5 ON ppd (datum,operator,edb,edb_fl);
CREATE INDEX ix_ppd_6 ON ppd (datum,operator,rb_obr,tabela_kod); 

正如您可以看到每个索引中的字段数据和运算符重复。 有人可以帮我重写它们以优化我的桌子吗?

直到现在我需要每两周运行一次UPDATE STATISTICS HIGH FOR TABLE ppd才能优化表ppd,但这不是一个好的解决方案,对吗?

1 个答案:

答案 0 :(得分:1)

如果您的查询未在datumoperator上指定条件(最好是相等条件),那么这些索引就没用了。服务器将不得不求助于扫描整个表,或者动态构建索引(并丢弃它们)。例如,使用查询:

SELECT *
  FROM ppd
 WHERE datum = DATE('2017-11-04')
   AND operator = 'JKL'
   AND …

这些索引中的任何一个都可能有用,具体取决于部分中指定的条件。

如果条件指定datumoperator上的范围而不是相等,则索引不太有用,但不一定无用。如果您执行WHERE operator MATCHES '*'之类的操作,则无法从索引中获益。例如:

SELECT *
  FROM ppd
 WHERE datum BETWEEN DATE('2017-11-04') AND DATE('2017-11-08')
   AND operator = 'JKL'
   AND …

优化器可能会使用索引,但它会为BETWEEN子句隐含的5个日期中的每个日期记录的所有运算符值选择数据。 'JKL'过滤器可能对优化器没有多大帮助。使用固定日期和一系列操作符,您可以从索引中获得更多好处,但它仍然有限。

如果您有类似的查询:

SELECT *
  FROM ppd
 WHERE client_id = 'ABC123DEF456Z'
   AND obrabot = 12345
   AND …{no mention of datum or operator}…

然后根本不能使用任何索引。

因此,您需要查看并显示运行缓慢的查询。您需要查看他们的查询计划(SET EXPLAIN输出)。保持统计信息更新很重要,但如果优化程序无法使用索引,则无济于事;实际上,在这种情况下,指数会适得其反。当插入,更新,删除行时,它们会占用空间并需要系统维护 - 但是在运行查询时不会使用它们。您可以添加索引以强制实施唯一性约束或加速查询。如果你的索引没有用于任何目的,它们毫无意义(你最好放弃它们)。

令人担心的是,所有索引都不是唯一的。这意味着您没有在表上定义主键。你应该有一个。

请注意,还有其他因素会影响性能。你和其他哪些桌子一起加入?您有5列CHAR(100)类型和其他列数量适中;您的行大小为794字节,这意味着如果Informix在您的系统上使用2K页面(页面大小为每页5行,页面大小为4K),则页面上只有2行。它们都是固定大小的字段,简化了事情。但是,与“慢速SQL看起来像什么”相比,这些都是次要问题。当然,如果您加入其他错误索引表,那么这种组合可能会对性能造成灾难性后果。