我一直在努力尝试优化几个查询消耗的时间和资源。我从perl脚本调用。问题如下:
预期行为 有一个包含超过4百万个寄存器的表,其中一个字段(我将其称之为f_path)此表是一个字符串,表示目录路径可能包含也可能不包含(大多数情况下)包含子字符串的字符串日期格式。脚本期望的行为是获取这些寄存器的子集,使用f_path中类似日期的子字符串对其进行过滤,并将它们存储在本地文件中以对它们执行某些操作并在某些图形生成中使用这些数据功能。过滤器的工作方式如下:获取f_path中具有对应日期子字符串的所有记录,这些记录位于用户定义的日期范围内。用户定义此范围,提供最后日期(要提取的最新日期)和表示从上一个日期向后提取的日期数的数字。日期遵循一个有点连续的模式,但不能指望(可能存在差距)。符合用户提供的过滤器参数的所有日期都将存储在perl,文件或两者中的变量中,因为它们稍后将被其他脚本使用,并且还用于控制提到的图形函数prevously。
当前行为: 没有过滤。当前查询获取所有400万个+寄存器并将它们存储在本地文件中,然后它在同一个表上运行另一个查询,该查询获取f_path的所有不同值(可以选择具有相同日期子字符串的几个值)即使日期相同,目录路径也可以是不同的)并将它们存储在perl中的局部变量中,稍后应用正则表达式来获取类似日期的子字符串并将它们存储在文件中。问题:这是非常低效的,因为它会查询整个表两次并恢复大量不会被使用的数据。
尝试修复: 遗憾的是,我所尝试过的所有内容都比当前的脚本更慢:
psql -U postgres -c "CREATE TEMP TABLE temp_filter_trees AS SELECT DISTINCT substring(proj_base, '[0-9]{4}_[0-9]{2}_[0-9]{2}') AS "TREE" FROM testcase ORDER BY TREE DESC LIMIT 30; SELECT mem_tot_size, mem_size_inc_pct, tot_sim_time, duration, cpu_util_pct, cpu_tot_time, result,
test_host, proj_base, topology FROM testcase, temp_filter_trees WHERE substring(proj_base, '[0-9]{4}_[0-9]{2}_[0-9]{2}') = temp_filter_trees.TREE " $proj > $dir/log_file
;
@data = psql -U postgres -c "SELECT DISTINCT substring(proj_base, '[0-9]{4}_[0-9]{2}_[0-9]{2}') AS "TREE" FROM testcase ORDER BY TREE DESC LIMIT 30" $proj
;
foreach(@data)
{
next unless m/(\d{4}\w{1}\d{2}\w{1}\d{2})$/;
if(defined $psqlpattern){
$psqlpattern = $psqlpattern ."|$1";
}
else{
$psqlpattern = "'" . $1;
}
push @trees, $1;
}
$ psqlpattern = $ psqlpattern。 “'”;
psql -U postgres -c "SELECT mem_tot_size, mem_size_inc_pct, tot_sim_time, duration, cpu_util_pct, cpu_tot_time, result,
test_host, proj_base, topology FROM testcase WHERE proj_base ~ $psqlpattern" $proj > $dir/log_file
;
其他想法:我还想过在查询中的f_path字段上使用子字符串查询来获取所有数据,以检查类似日期的子字符串是否在由指定的范围内用户通过询问它是否比过去的日期更早且比过滤器中的旧日期更新,无论如何必须先前获取。我没有试过这个,但似乎比我尝试的其他事情更有效率。
我们将非常感谢您提供的任何见解或帮助。谢谢你的时间!
答案 0 :(得分:1)
读取记录的perl i / o操作非常昂贵,尤其是对于4M记录。因此,我建议的一般方法是在数据库中尽可能多地完成工作,并专注于调优数据库查询。我也会尝试通过一次传递来实现这一点,并避免将记录复制到临时表。
所以作为一个起点,也许看看你是否可以通过使用psql的SIMILAR TO
运算符或可能regexp_matches
函数的单个查询来实现你想要的。然后根据日期添加另一个条件进行过滤。