加快Informix的SQL查询?

时间:2019-04-19 09:29:49

标签: sql query-optimization informix

在Informix上,可以加快此查询的速度吗?

SELECT FIRST 1 HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1  as dec,
           HEX(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1) as hex,
   SUBSTR((HEX(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1))::char(10), 6) as str
FROM informix.coordman as l
WHERE (SUBSTR(NVL(l.cm_code, ' '), 1, 2) = 'MU')
AND
NOT EXISTS (SELECT r.cm_code FROM informix.coordman r
            WHERE (SUBSTR(NVL(l.cm_code, ' '), 1, 2) = 'MU') AND
                  (SUBSTR(NVL(r.cm_code, ' '), 1, 2) = 'MU') AND
                  (HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1 =
                   HEX('0x'||SUBSTR(LPAD(NVL(r.cm_code, '0'), 7, '0') , 3))::INT) )
ORDER BY 1 ASC;

我已经尝试使用 LEFT OUTER JOIN 的版本,

SELECT FIRST 1 HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1 as dec,
HEX(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1) as hex,
SUBSTR((HEX(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1))::char(10), 6) as str,
r.cm_code
FROM informix.coordman as l
LEFT OUTER JOIN informix.coordman r ON
(SUBSTR(NVL(l.cm_code, ' '), 1, 2) = 'MU') AND
(SUBSTR(NVL(r.cm_code, ' '), 1, 2) = 'MU') AND
(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1 =
HEX('0x'||SUBSTR(LPAD(NVL(r.cm_code, '0'), 7, '0') , 3))::INT)
WHERE (SUBSTR(NVL(l.cm_code, ' '), 1, 2) = 'MU') and
r.cm_code IS NULL
ORDER BY 1 ASC;

但是我使速度恶化了。

更新 查询的目的是按照如下所示的顺序查找孔:

cm_code
MU00001
MU00001
MU00002
MU00002
...
MU0000B
MU0000B
MU0000D
MU0000D
...
MU00010
MU00010
MU00011

cm_code字段的类型为:

Column name          Type                                    Nulls
cm_code              char(8)                                 yes

为了加快速度,以前报告的查询已替换为:

SELECT FIRST 1 HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1 as dec, 
HEX(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1) as hex, 
SUBSTR((HEX(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1))::char(10), 6) as str 
FROM 
informix.coordman as l WHERE 
(SUBSTR(NVL(l.cm_code, ' '), 1, 2) = 'MU') 
ORDER BY 1 ASC

现在,我需要加快以下查询的速度:

SELECT FIRST 1 HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT + 1 as dec, 
HEX(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT + 1) as hex, 
SUBSTR((HEX(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT + 1))::char(10), 6) as str 
FROM 
informix.coordman as l WHERE 
(SUBSTR(NVL(l.cm_code, ' '), 1, 2) = 'MU') AND 
NOT EXISTS (SELECT r.cm_code FROM informix.coordman r WHERE 
(SUBSTR(NVL(l.cm_code, ' '), 1, 2) = 'MU') AND 
(SUBSTR(NVL(r.cm_code, ' '), 1, 2) = 'MU') AND 
(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT +1 = HEX('0x'||SUBSTR(LPAD(NVL(r.cm_code, '0'), 7, '0') , 3))::INT)) 
ORDER BY 1 ASC

1 个答案:

答案 0 :(得分:1)

我已经生成了两个版本的查询,一个版本需要Informix 14.10,另一个版本不需要。我已经根据您的查询对它们进行了基准测试,并获得了惊人的结果。我正在使用其中有360行的表,它是随机生成的。对于一组数据,这导致85行,该行出现一次,67次出现两次,26次出现三次,8次出现四次,5次出现五次,1次出现六次。

结果:

Q0      0.7212 seconds — as in question
Q1      0.0044 seconds — using CTE
Q2      0.0027 seconds — using an explicit temporary table
                        (add 0.0006 seconds if the temp table is dropped explicitly)

我不确定为什么Q1和Q2之间会有如此大的差异,但是与Q0相比,两者可以忽略不计。

此SQL脚本显示了我执行的操作,需要我的SQLCMD程序,该程序可从IIUG(International Informix Users Group获得。它还使用自制的随机数据生成器。

!random -n 360 -F "MU%5X" 1 255 > "so-5575-9624.unl"

DROP TABLE IF EXISTS coordman;
CREATE TABLE coordman
(
    cm_code CHAR(8) NOT NULL
);

RELOAD FROM "so-5575-9624.unl" INSERT INTO coordman;
CREATE INDEX i_cm_code ON coordman(cm_code);

types on;
headings on;
trace on;

--SELECT {FIRST 1}   HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1  AS DEC,
SELECT DISTINCT    HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1  AS DEC,
               HEX(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1) AS HEX,
       SUBSTR((HEX(HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1))::CHAR(10), 6) AS str
  FROM coordman AS l
 WHERE (SUBSTR(NVL(l.cm_code, ' '), 1, 2) = 'MU')
   AND NOT EXISTS
       (SELECT r.cm_code FROM coordman AS r
         WHERE (SUBSTR(NVL(l.cm_code, ' '), 1, 2) = 'MU') AND
               (SUBSTR(NVL(r.cm_code, ' '), 1, 2) = 'MU') AND
               (HEX('0x'||SUBSTR(LPAD(NVL(l.cm_code, '0'), 7, '0') , 3))::INT - 1 =
                HEX('0x'||SUBSTR(LPAD(NVL(r.cm_code, '0'), 7, '0') , 3))::INT)
       )
ORDER BY 1 ASC;

WITH cm_numbers AS
     (SELECT DISTINCT cm_code,
            --('0x'||cm_code[3,8])               AS hex_string,
            --('0x'||cm_code[3,8])::INT          AS dec_value,
            --('0x'||SUBSTR(cm_code, 3, 6))      AS hex_substr,
            ('0x'||SUBSTR(cm_code, 3, 6))::INT AS dec_number
       FROM coordman AS l
      WHERE cm_code[1,2] = "MU"
     )
SELECT l.dec_number - 1 AS missing_number, l.cm_code
  FROM cm_numbers AS l
  LEFT JOIN cm_numbers AS r
    ON l.dec_number - 1 = r.dec_number
 WHERE r.dec_number IS NULL
 ORDER BY missing_number;

DROP TABLE IF EXISTS cm_numbers;

SELECT DISTINCT cm_code, ('0x'||SUBSTR(cm_code, 3, 6))::INT AS dec_number
  FROM coordman AS l
 WHERE cm_code[1,2] = "MU"
  INTO TEMP cm_numbers;

SELECT l.dec_number - 1 AS missing_number, l.cm_code
  FROM cm_numbers AS l
  LEFT JOIN cm_numbers AS r
    ON l.dec_number - 1 = r.dec_number
 WHERE r.dec_number IS NULL
 ORDER BY missing_number;

DROP TABLE IF EXISTS cm_numbers;

主要区别在于所调用函数的绝对数量。另外,如注释中所述,您可以使用NVL防止空值,但是您不会利用返回值。