【问题标题】:How do I use tablename placeholders in a prepared statement?如何在准备好的语句中使用表名占位符?
【发布时间】:2011-07-26 06:57:39
【问题描述】:

我需要一些 Perl 帮助来调整此代码以优化此 DBI prepare 语句的使用。我确信我可以进一步优化/加速它。我想我在有一个连接的地方已经正确设置了这个设置,但我想确保我只解析一次查询并只替换唯一的 (1) 参数更改。我只是不确定如何安排。

我基本上是在获取一个表列表并将这些表循环作为单个查询的输入。基本上,这是具有不同表名的相同查询。

谁能告诉我如何优化它?

这是我正在编写的代码:

my @tbls = qx(mysql -u foo -pf00 --database $dbsrc -h $node --port 3306 -ss -e "show tables");
my $dbh = DBI->connect("DBI:mysql:database=$dbsrc;host=$node;port=3306",'foo','f00');

# Creating a logfile
open (MYLOG, ">$dmpdir$node-mytstdmp-$dt.log") || die "cannot append";

# Loop through each table and create its own data file
foreach my $tbls (@tbls)
{
   chomp $tbls;
   print MYLOG "START Time ==> ", &dt2, "\n";
   extract_data($dbh, $tbls);
   print MYLOG "TIME END  ==> ", &dt2, "\n";
};
$dbh->disconnect;
close (MYLOG);

sub extract_data
{
     my($dbh, $tbls) = @_;
     my $out_file = "$dmpdir$node-$tbls.$dt.out";
     open (my $gzip_fh, "| /bin/gzip -c > $out_file.gz") or die "error starting gzip $!";
     print MYLOG "Creating dmp file ==> $out_file.gz\n";
     my $sth = $dbh->prepare("SELECT UUID(), '$node', 1, 2, flg, upd, vts FROM $tbls");
     $sth->execute();
     while (my($uid, $hostnm,$1,$2,$flg,$upd,$vts) = $sth->fetchrow_array() ) {
       print $gzip_fh "_key_$uid^Ehost^A$hostnm^E1^A$1^E2^A$2^Eflg^A$flg^Eupd^A$upd^Evts^A$vts^D";
     }
     $sth->finish;
     close $gzip_fh or die "Failed to close file: $!";
};

【问题讨论】:

    标签: perl prepared-statement dbi


    【解决方案1】:

    表名不能作为参数执行。这记录在perldoc DBI:

    With most drivers, placeholders can't be used for any element of a statement
    that would prevent the database server from validating the statement and
    creating a query execution plan for it. For example:
    
      "SELECT name, age FROM ?"         # wrong (will probably fail)
      "SELECT name, ?   FROM people"    # wrong (but may not 'fail')
    

    顺便说一句,如果你想优化这段代码,你应该先把对mysql的调用替换为对DBI的调用:

    my @tbls = @{ $dbh->selectcol_arrayref('SHOW TABLES') };
    

    【讨论】:

    • 反正也没多大用处,查询计划只是有点依赖于有问题的表。
    • 好的,感谢您的澄清和您的意见。我还看到?WHERE 子句一起使用。
    【解决方案2】:

    通过诸如NYTProf 之类的分析器运行您的代码。这将告诉您您在计划中花费的所有时间。

    但实际上,我觉得它很好。抛开编码问题不谈(你使用 typeglobs 作为文件句柄,你使用 open() 的两个参数形式,你没有在查询中使用占位符)我不认为你可以从性能中做更多的事情问题。但是,您需要进行适当的分析来确定这一点。

    【讨论】:

      【解决方案3】:

      一般来说 fetchrow_arrayref 比 fetchrow_array 更快,因为它重用了数组。如果与绑定列结合使用,它通常会更快,但请阅读 fetchrow_arrayref 的 DBI 文档,因为您必须小心不要存储对返回数据的引用(您没有这样做)。 fetchall_arrayref 也可能比您在此处执行的操作更快,但这在很大程度上取决于您的选择返回多少行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-05-23
        • 2015-03-14
        • 1970-01-01
        • 2018-06-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多