【DB2】SQL优化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【DB2】SQL优化相关的知识,希望对你有一定的参考价值。

参考技术A

于我来说,我喜欢技术,不偏执于某一类开发语言,愿意花时间精力去解决问题。

1.去除在谓词列上编写的任何标量函数

优化前:(耗时3.1s)

优化后:(耗时0.922s)

总结:

DB2可以选择使用START_DATE上的列索引,但是在列上使用了函数后,DB2就无法使用列索引了,从而导致查询效率变低。

2.去除在谓词列上编写的任何数学运算

优化前:(耗时10.265)

优化后:(耗时3.39s)

总结:

DB2查询时候,会优先选择列CONTRACT_AMT上的索引,如果直接对列CONTRACT_AMT应用数学运算,DB2就无法使用索引了。一定要做到:列本身(不加数学运算)放在操作符的一边,而所有的计算都放在另外一边。

3.SQL语句中指定查询列

优化前:(耗时13.15s)

优化后:(耗时2.922s)

总结:

如果Select包含不需要的列,优化工具会选择Indexonly=’N’,这会强制DB2必须进入数据页来得到所请求的特定列,这就要求更多的I/O操作,梁歪,这些多余的列可能是某些排序的部分,这样一来就需要和传递一个更大的排序文件,相应的会使排序成本更高。

4.尽可能不使用distinct

优化前:(耗时0.687s)

优化后:(耗时0.437s)

总结:

在测试distinct与group by性能的过程中,在列CST_ID上添加索引后,发现group by 确实比distinct快一些,但是在数据分布比较离散的情况下使用group by ,比较集中的情况下使用distinct.表数据量较少的情况随便使用哪个都一样, 不管选择谁,都要建立索引

5.Exists、in、not in 、not exists的使用场景选择

5.1 in跟exists的区别:

例如:表A(小表),表B(大表)

优化前:(耗时1.93s)

优化后:(耗时1.125s)

相反的,

优化前:(耗时1.9s)

优化后:(耗时1.0s)

总结:

in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询,一直以来认为exists比in效率高的说法是不准确的。 如果查询的两个表大小相当,那么用in和exists差别不大;如果两个表中一个较小一个较大,则子查询表大的用exists,子查询表小的用in;

简称:子大Exists,子小in

5.2 not in 与 not exists区别:

如果查询语句使用了not in,那么对内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比not in 要快。

6.尽可能使用union all来代替union

优化前:(耗时15.344s)

优化后:(耗时2.719s)

总结:

在union中,DB2最后会自动执行一个排序来消除重复值,这样是很耗费资源的,所以在不需要去重复的情况下,尽可能使用UNION ALL 代替union

N.模板

优化前:(耗时3.1s)

优化后:(耗时0.922s)

总结:

如何针对 db2 数据库优化 SQL/Python 选择查询?

【中文标题】如何针对 db2 数据库优化 SQL/Python 选择查询?【英文标题】:How to optimize SQL/Python select queries against a db2 database? 【发布时间】:2021-08-06 14:11:13 【问题描述】:

通过 Python 连接到服务器上的 db2 数据库并查询一个巨大的表(可能有 200 万条记录,50 列)。此表用于分析(OLAP 可能是正确的术语)而不是事务。我想优化我的 sql/python 代码以更快地执行查询。

没有深入了解sql查询,我的怀疑是SELECT语句从表的第一条记录开始,一直持续到满足查询为止。 FETCH FIRST 10 ROWS ONLY 在 WHERE date_col > 20210701 需要在识别前 10 条记录之前扫描几条 1 亿条记录——执行此查询需要几分钟以上的时间。通过游标对象的性能类似。

或者,我通过 Microsoft Access 连接到同一个表。 Access 中相同的日期查询在 <.5>SELECT 语句还要快。 Access 肯定在幕后做着我不知道的事情。

所以Access证明了这些sql查询可以快速执行的概念。我留下了一个问题:如何优化我的 sql/python 代码以匹配 Microsoft Access 的性能?谢谢大家。

import ibm_db_dbi as db
import pandas as pd 

cnxn = db.connect(dsn=     '********', 
                  user=    '********', 
                  password='********', 
                  host=    '********', 
                  database='********')   

cols = "0col1, 0col2, 0col3, 0col4".format('database.')

# Executes in <1 second
fast_sql = '''SELECT  FROM bigtable
              FETCH FIRST 10 ROWS ONLY'''.format(cols)

# Executes in ~5 seconds 
slower_sql = '''SELECT  FROM bigtable
                WHERE col1 = 1234
                FETCH FIRST 10 ROWS ONLY'''.format(cols)

# Giving up after ~3 minutes
slowest_sql = '''SELECT  FROM bigtable 
                       WHERE date_col > 20210701
                       FETCH FIRST 10 ROWS ONLY'''.format(cols) 

df = pd.read_sql_query(horribly_slow_sql , cnxn)

cnxn.close()

【问题讨论】:

您需要查看在每种情况下实际发送到数据库服务器的查询。另外,您如何衡量执行时间? 任何索引?有关表设计的任何信息? date_col 是什么类型?从一些性能基础开始,即在可重现的环境中收集事实。 “mil”是指几百万还是几千? @mustaccio 如何找到从 Microsoft Access 发送到数据库的实际 sql?到目前为止,谷歌没有帮助。有什么想法吗? @data_henrik 感谢您的回复。通过访问探索“对象定义”属性表明有 7 个索引。不过它们有点神秘,所以我不确定它们实际上是如何传递到 Access 的 sql 查询中的。不过,这是一个很好的起点。 【参考方案1】:

有几个因素影响了这个问题。

    最重要的是一个简单的数据类型问题。 date_col 不是整数也不是日期时间,而是 CHAR 格式。这导致了索引问题,导致查询缓慢。通过将结果放在引号中解决了问题:...WHERE date_col &gt; '20210701' 而不是 ...WHERE date_col &gt; 20210701

    另一个问题是对 Access 如何处理数据的误解。切换到“数据表视图”时,Access 不会执行整个查询。相反,它执行与FETCH FIRST 50 ROWS ONLY 等效的操作。查询出现得如此之快,因为服务器不需要将整个数据集发送给客户端。但是,导出时会执行整个查询。在我的例子中,这大约需要 5 秒,代表一个相当于我正在执行的 Python 脚本的过程。

谢谢大家的上述cmets。

【讨论】:

以上是关于【DB2】SQL优化的主要内容,如果未能解决你的问题,请参考以下文章

如何针对 db2 数据库优化 SQL/Python 选择查询?

需要帮助优化涉及数百万条记录的非常慢的 DB2 SQL 查询

db2 优化基础 查询运行时间最长的SQL

db2分页技术优化问题:

redis详情-----介绍优化。。。。

Mysql学会查看sql的执行计划