如何优化SQL查询并创建索引

问题描述 投票:0回答:1
我需要为不同类型的残疾产生统计数据,并计算有多少妇女在2018年开始患每种状况的妇女在一月(一年中的第一个月)中受到影响。我需要跟踪的条件是:

    精神疾病
  • 认知障碍
  • 社会疾病
  • 数据存储在表中,我需要:

对每个条件的数据重新删除。 在2018年的第一个月中,每周(第一,第二,第三和第4周)将数据分解。 根据以下事实过滤女性的数据,即出生人数的第二和第三位数大于或等于51。 SELECT disability_name, SUM(CASE WHEN TO_CHAR(start_date, 'IW') = '01' THEN 1 ELSE 0 END) AS first_week, SUM(CASE WHEN TO_CHAR(start_date, 'IW') = '02' THEN 1 ELSE 0 END) AS second_week, SUM(CASE WHEN TO_CHAR(start_date, 'IW') = '03' THEN 1 ELSE 0 END) AS third_week, SUM(CASE WHEN TO_CHAR(start_date, 'IW') = '04' THEN 1 ELSE 0 END) AS fourth_week FROM p_disabilities JOIN p_disability_type ON p_disabilities.id_disability = p_disability_type.disability_id WHERE TO_CHAR(start_date, 'YYYY') = '2018' AND TO_CHAR(start_date, 'MM') = '01' AND TO_NUMBER(SUBSTR(birth_number, 3, 2)) >= 51 GROUP BY disability_name; 我正在尝试简化此SQL查询,以提高其效率。具体来说,我想提高查询的性能,因为它正在使用潜在的大型数据集。我可以简化或优化此查询的一些方法?

地,在涉及的表上使用的最合适的索引是什么,尤其是在

start_date

Birth_number

disability_id

中,以确保此查询尽可能快地运行? 表格的标题:

CREATE TABLE p_disabilities ( id_disability CHAR(6) NOT NULL PRIMARY KEY, birth_number CHAR(11) NOT NULL, start_date DATE NOT NULL, end_date DATE NOT NULL, disability_id NUMBER NOT NULL ); CREATE TABLE p_disability_type ( disability_id NUMBER NOT NULL, disability_name VARCHAR2(50) ); try以免在WHERE

子句中的列上应用功能。使用日期/时间范围时,我们通常使用包含的下限和独家上限。至于出生号码基因:当然,没有办法避免使用

SUBSTR。 (但是第二/第三位应该是SUBSTR(birth_number, 2, 2)

如果我没记错的话。)
查询将看起来像这样:
oracle-database performance optimization indexing
1个回答
0
投票
SELECT dt.disability_name, SUM(CASE WHEN TO_CHAR(d.start_date, 'IW') = '01' THEN 1 ELSE 0 END) AS first_week, SUM(CASE WHEN TO_CHAR(d.start_date, 'IW') = '02' THEN 1 ELSE 0 END) AS second_week, SUM(CASE WHEN TO_CHAR(d.start_date, 'IW') = '03' THEN 1 ELSE 0 END) AS third_week, SUM(CASE WHEN TO_CHAR(d.start_date, 'IW') = '04' THEN 1 ELSE 0 END) AS fourth_week FROM p_disabilities d JOIN p_disability_type dt ON dt.disability_id = d.id_disability WHERE d.start_date >= DATE '2018-01-01' AND d.start_date < DATE '2018-02-01' AND TO_NUMBER(SUBSTR(d.birth_number, 2, 2)) >= 51 GROUP BY dt.disability_name ORDER BY dt.disability_name;

WHERE
子句中最选择性的列是start_date,您可以从整个表中选择一个月。 Birth_number子字符串的选择性较小,因为您接受了可能的一半值。因此,适当的索引看起来像这样:
CREATE INDEX idx ON p_disabilities (start_date, TO_NUMBER(SUBSTR(d.birth_number, 2, 2)));

这是一个函数索引,其中包括我们索引的计算值。替代方案是计算的列:

ALTER TABLE p_disabilities ADD sex AS (CASE WHEN TO_NUMBER(SUBSTR(birth_number, 2, 2)) >= 51 THEN 'f' ELSE 'm' END);
然后将其索引并在查询中使用,我发现它更可读。
您可以在要在查询中使用的索引末尾的列,从加入的ID_DISANE开始,而有条件的聚合开始。然后,索引可能会这样lok:

TO_CHAR(d.start_date, 'IW')

日期/周的注释:虽然使用ISO Week是许多情况的好方法,但我在这里不合适,因为第一个ISO周可以在上一年开始,并且仅通过查看一月,您可能会度过四天的一周。考虑以某种方式更改此操作(例如,通过查看1月1-7日,8-14,...而不是)。
	

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.