Я извлекаю данные в SAS из базы данных сервера SQL с помощью преобразования извлечения (SAS DI).Данные в таблице возвращаются несколько лет назад и насчитывают чуть более 16 миллионов строк;Мне нужны только данные за последние несколько лет, которые должны составить примерно 2,6 млн. Строк.
Так что в моей выписке используется фильтр даты и времени.Автоматически сгенерированный процесс sql выглядит следующим образом (после обфускации имен libref, table и column):
%let SYSLAST = %nrquote(LIBREF.SRC_TBL);
proc sql;
create table work.WFJVX4PU as
select
col1,
col2,
dt_col,
col3
from &SYSLAST
where dt_col >= &start_dt
;
quit;
Код работает и возвращает нужные строки , но это занимает слишком много временизапускаться по сравнению с выполнением аналогичного запроса непосредственно на сервере SQL.При проверке статистики выполнения я обнаружил, что вся таблица была перенесена в SAS до применения условия where.
Я помню, что читал, что это произойдет при попытке использовать фильтры, которые применяют функции к исходным данным (а-ля datepart(dt_col) >= input("&start_date",date9.)
), поэтому я попытался передать дату и время, использованные фильтром, непосредственно в движок SQL.Я также попробовал подход "datepart
" и получил тот же результат.
Есть ли что-то еще, что я должен сделать, чтобы применить сторону сервера фильтрации перед переносом данных в SAS?Это не тот опыт, который был у меня в прошлом при работе с другими таблицами базы данных (например, Teradata, MySQL, Oracle и т. Д.).
Дополнительные сведения:
Макропеременная start_date
определяется с помощью инструмента создания подсказок SAS DI;автоматически сгенерированный код для этого
%let start_date_label = 730 days ago (July 02, 2017);
%let start_date_rel = D-730D;
%let start_date = 02Jul2017;
Затем я создаю макрос-переменную datetime start_dt
, выполнив в прекоде задания следующую команду:
%let start_dt = %sysfunc(dhms("&start_date"d,0,0,0));
Ниже приведеноператор libname (после запутывания):
LIBNAME MYLIB SQLSVR CONNECTION=SHARED PRESERVE_TAB_NAMES=YES dbconinit="set ansi_warnings off;use MY_DB_NAME;set nocount on;" Datasrc=MY_DATA_SRC SCHEMA=dbo AUTHDOMAIN="my_sql_authentication" ;
Если я изменю предложение where для использования литерала формы '2019-06-25'
, тогда SAS выдаст ошибку
ERROR: выражение с использованиембольше или равно (> =) имеет компоненты разных типов данных.
, поскольку поле dt_col
имеет тип numeric (format datetime22.3
) на экземпляре SAS сервера SQLтаблица, которая зарегистрирована из библиотеки.Если я использую литерал следующим образом:
dt_col >= '25JUN2019'D
, тогда я получаю желаемый набор строк (несмотря на сравнение между полем datetime и литералом даты), но запрос по-прежнему принимаетвыполняется долго, и статистика заданий показывает, что SAS все еще захватывает все 16 миллионов строк для выполнения этой задачи.
ОБНОВЛЕНИЕ
У меня проблемы по совету Томаниже.Если я выполняю следующий код:
LIBNAME MYLIB SQLSVR CONNECTION=SHARED PRESERVE_TAB_NAMES=YES dbconinit="set ansi_warnings off;use MYDB;set nocount on;" Datasrc=MYSRC SCHEMA=dbo AUTHDOMAIN="my_sql_authentication" ;
/*---- Map the columns ----*/
proc datasets lib = work nolist nowarn memtype = (data view);
delete sql_psthru2;
quit;
proc sql;
create table work.sql_psthru2 as
select
col1,
col2,
dt_col,
col3
from MYLIB.MYTBL
where dt_col>= '25JUN2019'd
;
quit;
, тогда я получаю данные из базы данных, но если я выполняю
LIBNAME MYLIB SQLSVR CONNECTION=SHARED PRESERVE_TAB_NAMES=YES dbconinit="set ansi_warnings off;use MYDB;set nocount on;" Datasrc=MYSRC SCHEMA=dbo AUTHDOMAIN="my_sql_authentication" ;
proc sql;
connect using MYLIB;
create table work.sql_psthru as
select * from connection to MYLIB
(select
col1
,col2
,dt_col
from MYTBL
where dt_col >= '2019-06-25'
)
;
quit;
, тогда я получаю ошибку
ОШИБКА: ошибка CLI при попытке установить соединение: [DataDirect] [ODBC lib] Не найдено имя источника данных и не указан драйвер по умолчанию
сразу после строки connect using MYLIB;
.Я перепробовал много вариантов явного passthru, которые я нашел по всему Интернету, но я не буду публиковать здесь, но ни один из них не сработал.
Интересным примечанием является то, что я считаю причину SAS DIСтатистика показывает, что все 16 миллионов строк возвращаются в том, что преобразование извлечения автоматически генерирует следующий макрос:
%macro etls_recordCheck;
%let etls_recCheckExist = %eval(%sysfunc(exist(MYLIB.MYTBL, DATA)) or
%sysfunc(exist(MYLIB.MYTBL, VIEW)));
%if (&etls_recCheckExist) %then
%do;
proc sql noprint;
select count(*) into :etls_recnt from MYLIB.MYTBL;
quit;
%end;
%mend etls_recordCheck;
%etls_recordCheck;
Таким образом, виновник в длительном времени выполнения не в том, что полный набор данных возвращается в SAS(Я удалил макрос, и выполнение кода по-прежнему занимает слишком много времени).