Я некоторое время пытался оптимизировать время и ресурсы, потребляемые парой запросов, которые я вызываю из Perl-скрипта. Проблема заключается в следующем:
Ожидаемое поведение:
Существует таблица с более чем 4 миллионами регистров, одно из полей (я буду называть ее f_path с этого момента) этой таблицы представляет собой строку, которая обозначает путь к каталогу, который может или не может (большинство из них) содержать подстроку в Формат даты. Поведение, ожидаемое от сценария, состоит в том, чтобы взять подмножество этих регистров, отфильтровать его, используя подстроки типа даты из f_path, и сохранить их в локальном файле, чтобы выполнить некоторые операции над ними и использовать данные в некоторой графической генерации. функции. Фильтр должен работать следующим образом: получить все записи с соответствующей подстрокой даты в f_path, которые находятся в определенном пользователем диапазоне дат. Пользователь определяет этот диапазон, предоставляя последнюю дату (самую новую дату для извлечения) и число, представляющее, сколько дат нужно извлечь из последней даты назад. Даты следуют несколько последовательному шаблону, но на это нельзя рассчитывать (могут быть пробелы). Все даты, которые соответствуют параметрам фильтра, предоставленным пользователем, должны храниться в переменной в perl, в файле или в обеих, так как они будут использоваться другими сценариями позже, а также используются для управления упомянутыми функциями графа. Данные о предыдущих.
Текущее поведение:
Там нет фильтрации. Текущий запрос выбирает все 4 миллиона + регистров и сохраняет их в файле локально, затем выполняет еще один запрос к той же таблице, который выбирает все различные значения для f_path (можно выбрать пару значений с одной и той же подстрокой даты, так как путь к каталогу может отличаться, даже если дата совпадает), и сохраняет их в локальной переменной в perl, где позднее применяется регулярное выражение для извлечения подстрок типа даты и сохранения их в файле. Проблема: это совершенно неэффективно, поскольку он запрашивает всю таблицу дважды и восстанавливает большое количество данных, которые не будут использоваться.
Попытки исправить:
К сожалению, все, что я пробовал, оказалось даже медленнее, чем текущий скрипт:
- Создайте временную таблицу из операции выбора в таблицу со всеми данными, используя функцию подстроки, регулярное выражение и параметры фильтра, предоставленные пользователем для получения набора дат (не весь путь к каталогу, который является значение f_path) для использования в качестве фильтра. Затем создайте соединение между этой таблицей и таблицей с необходимыми данными в поле f_path (которое на самом деле называется proj_base), применяя функцию substring, чтобы получить подстроку, подобную дате, и проверьте, совпадает ли она с каким-либо из значений в временная таблица. Этот подход имеет дополнительный недостаток, заключающийся в том, что, как и в случае с текущим сценарием, мне придется запросить таблицу позже в сценарии, чтобы получить набор дат, которые действуют как фильтр. Возможно, я смогу использовать временную таблицу, которую я создал ранее, но я не уверен, будет ли она еще, когда я снова запросю даты, не пробовал. Это выглядит так:
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 в запросе, который выбирает все данные, чтобы проверить, находится ли подобная дате подстрока в диапазоне, заданном пользователемпросто спросив, является ли он старше, чем последняя дата, и новее, чем более старая дата в фильтре, которая должна быть предварительно выбрана в любом случае.Я не пробовал этого, но казалось, что это может быть, по крайней мере, немного более эффективным, чем другие вещи, которые я пробовал.
Любое понимание или помощь, которую вы можете предоставить, будет принята с благодарностью.Спасибо за ваше время!