SQL查询性能优化(TimesTen)

Posted

技术标签:

【中文标题】SQL查询性能优化(TimesTen)【英文标题】:SQL query performance optimization (TimesTen) 【发布时间】:2010-06-01 10:17:31 【问题描述】:

我需要一些有关 TimesTen DB 查询优化的帮助。我用 Java profiler 做了一些措施,找到了花费大部分时间的代码部分(这个代码部分执行 SQL 查询)。奇怪的是,这个查询只对某些特定的输入数据变得昂贵。

这是一个例子。我们有两个要查询的表,一个代表我们要获取的对象(T_PROFILEGROUP),另一个代表来自其他表的多对多链接(T_PROFILECONTEXT_PROFILEGROUPS)。我们不是在查询链接表。

这些是我在运行 DB Profiler 时执行的查询(除了 ID 之外它们是相同的):

Command> select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1464837998949302272;
< 1169655247309537280 >
< 1169655249792565248 >
< 1464837997699399681 >
3 rows found.

Command> select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1466585677823868928;
< 1169655247309537280 >
1 row found.

这是我在分析器中的内容:

12:14:31.147       1 SQL      2L    6C  10825P Preparing: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1464837998949302272
12:14:31.147       2 SQL      4L    6C  10825P sbSqlCmdCompile ()(E): (Found already compiled version: refCount:01, bucket:47) cmdType:100, cmdNum:1146695.
12:14:31.147       3 SQL      4L    6C  10825P Opening: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1464837998949302272;
12:14:31.147       4 SQL      4L    6C  10825P Fetching: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1464837998949302272;
12:14:31.148       5 SQL      4L    6C  10825P Fetching: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1464837998949302272;
12:14:31.148       6 SQL      4L    6C  10825P Fetching: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1464837998949302272;
12:14:31.228       7 SQL      4L    6C  10825P Fetching: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1464837998949302272;
12:14:31.228       8 SQL      4L    6C  10825P Closing: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1464837998949302272;
12:14:35.243       9 SQL      2L    6C  10825P Preparing: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1466585677823868928
12:14:35.243      10 SQL      4L    6C  10825P sbSqlCmdCompile ()(E): (Found already compiled version: refCount:01, bucket:44) cmdType:100, cmdNum:1146697.
12:14:35.243      11 SQL      4L    6C  10825P Opening: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1466585677823868928;
12:14:35.243      12 SQL      4L    6C  10825P Fetching: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1466585677823868928;
12:14:35.243      13 SQL      4L    6C  10825P Fetching: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1466585677823868928;
12:14:35.243      14 SQL      4L    6C  10825P Closing: select G.M_ID from T_PROFILECONTEXT_PROFILEGROUPS CG, T_PROFILEGROUP G where CG.M_ID_EID = G.M_ID and CG.M_ID_OID = 1466585677823868928;

很明显,第一个查询花了将近 100 毫秒,而第二个查询是立即执行的。这与查询预编译无关(第一个也是预编译的,因为之前发生了相同的查询)。我们为此处使用的所有列提供数据库索引:T_PROFILEGROUP.M_IDT_PROFILECONTEXT_PROFILEGROUPS.M_ID_OIDT_PROFILECONTEXT_PROFILEGROUPS.M_ID_EID

我的问题是:

为什么查询同一组表会在不同参数下产生如此不同的性能? 这里涉及到哪些索引? 有什么方法可以改进这个简单的查询和/或数据库以使其更快?

更新:给大小的感觉:

Command> select count(*) from T_PROFILEGROUP;
< 183840 >
1 row found.

Command> select count(*) from T_PROFILECONTEXT_PROFILEGROUPS;
< 2279104 >
1 row found.

【问题讨论】:

【参考方案1】:

我不熟悉 TimesTen,但假设它像其他关系数据库一样工作(除了在内存中),一个可能的原因是 T_PROFILECONTEXT_PROFILEGROUP.M_ID_OID 或 T_PROFILEGROUP.M_ID 列上没有索引或二叉树索引不平衡。

如果没有索引,结果将取决于数据的顺序以及它找到它们的速度。

在包含大量数据的表中,我遇到过不平衡的二叉树索引导致问题,因为树的一侧远大于其他侧。在这种情况下,重建索引可以重新平衡树。

我不能老实说这是否适用于 TimesTen 从未使用过它并且我的网络搜索没有产生太多信息。

【讨论】:

【参考方案2】:

我对 TimesTen 数据库不太熟悉,但由于它在这里不到 1/10 秒,这可能只是两个查询的舍入差异还是某种打嗝?

这里有一个link,它介绍了一些调整 TimesTen DB 性能的方法。它有一些一般信息(使用准备等)以及有关调整特定查询的信息。希望对你有帮助。

【讨论】:

当然不是。我分析了数千次执行此查询的 Java 代码,它显然成为性能瓶颈,仅对于导致此连接返回多行的 ID。【参考方案3】:

我粗略的打赌,第一个查询将数据从磁盘或虚拟内存中提取到实际内存中,第二个查询可以利用这一点。

你能用三个(或十个?)查询运行这个并报告回来吗?

【讨论】:

以上是关于SQL查询性能优化(TimesTen)的主要内容,如果未能解决你的问题,请参考以下文章

如何进行SQL性能优化

优化SQL查询:如何写出高性能SQL语句

逆水行舟 —— SQL优化之慢查询和explain以及性能分析

MySQL性能优化

SQL查询优化

SQL 查询优化:标量子查询是不是会影响性能?