相同的查询,两种不同的方式,性能差异很大

时间:2012-02-13 23:16:28

标签: perl postgresql dbi

我有一个超过800万行的Postgres表。考虑到通过DBD::Pg执行相同查询的以下两种方式,我得到了截然不同的结果。

$q .= '%';

## query 1
my $sql = qq{
    SELECT a, b, c
    FROM t 
    WHERE Lower( a ) LIKE '$q'
};
my $sth1 = $dbh->prepare($sql);
$sth1->execute();

## query 2
my $sth2 = $dbh->prepare(qq{
    SELECT a, b, c
    FROM t  
    WHERE Lower( a ) LIKE ?
});
$sth2->execute($q);

查询2至少比查询1慢一个数量级...似乎它没有使用索引,而查询1正在使用索引。

爱会听到原因。

5 个答案:

答案 0 :(得分:5)

对于LIKE表达式,只有在搜索模式为左锚定时才能使用b树索引,即% 终止。 More details in the manual
感谢@evil otto的链接。此链接指向当前版本。

您的第一个查询在准备时提供此基本信息,因此查询计划程序可以使用匹配的索引。

您的第二个查询在准备时没有提供有关模式的任何信息,因此查询规划器不能使用任何索引。

答案 1 :(得分:1)

我怀疑在第一种情况下,查询编译器/优化器检测到该子句是常量,并且可以构建最佳查询计划。在第二个中,它必须编译更通用的查询,因为绑定变量可以是运行时的任何内容。

答案 2 :(得分:0)

您是否使用相同的$ dbh对象从同一文件运行两个测试用例? 我认为在第二种情况下提高速度的原因是你使用已经解析的预处理语句(但可能我错了:))。

答案 3 :(得分:-1)

啊,我明白了 - 因为我不知道Perl,所以我会在评论之后退学。但我相信编辑器在强调$ q作为常量时是正确的。我猜你需要将值连接到字符串中,而不是直接引用变量。所以,我的猜测是如果+用于perl中的字符串连接,那么使用类似的东西:

my $ sql = qq {     选择a,b,c     从T     下(a)LIKE' } + $ q + qq {'};

(注意:除非语言与数据库紧密集成,例如Oracle / PLSQL,否则通常必须在提交到数据库之前创建一个完全有效的SQL字符串,而不是期望编译器'插入'/'替换'变量的值。)

我会再次建议您获取语句的COUNT(),以确保您将苹果与苹果进行比较。

答案 4 :(得分:-2)

我根本不知道Postgres,但我认为在第7行(WHERE Lower(a)LIKE'$ q' ),$ q实际上是一个常量。看起来你的编辑也这么认为,因为它以红色突出显示。你可能还需要使用?对于变量。

要进行测试,请执行COUNT(*),并确保它们匹配 - 我可能会离开。