Извлечение данных SQL Server в SAS с использованием фильтра даты и времени - PullRequest
0 голосов
/ 02 июля 2019

Я извлекаю данные в 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(Я удалил макрос, и выполнение кода по-прежнему занимает слишком много времени).

1 Ответ

0 голосов
/ 03 июля 2019

Вы можете попробовать явно записать код в удаленной базе данных. Поэтому, если у вас уже есть определенный libref с именем LIBREF, вы можете использовать его в операторе CONNECT в PROC SQL.

proc sql;
 connect using libref ;
 create table WFJVX4PU as
   select * from connection to libef
   (select
      col1
     ,col2
     ,dt_col
     ,col3
    from SRC_TBL
    where dt_col >= &start_dt
  )
 ;
quit;

Просто убедитесь, что все внутри () является допустимым синтаксисом для этой системы баз данных. Включены значения макропеременной START_DT.

...