在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
答案 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
防止空值,但是您不会利用返回值。