Индексы в PROC DATASETS, PROC SQL для библиотек SAS и ORACLE

Меня немного смущает использование индексов в SAS.

Я нашел 2 способа их реализации:

с PROC SQL

CREATE <UNIQUE> INDEX index-name 
 ON table-name ( column <, ... column>);  

с наборами данных PROC

proc datasets library=college;
   modify survey;
      index create class;
      index create major;
run;

proc datasets library=college;
   modify maillist;
      index create zipid=(zipcode schoolid);
run;

proc datasets library=college;
   modify student;
      index create idnum / unique;
run;

proc datasets library=college;
   modify student;
      index create religion / nomiss;
run;

Мой первый вопрос: они делают то же самое? Я бы предположил, что они есть, но, учитывая, что в документе нет перекрестных ссылок на них и что нет варианта для nomiss в PROC SQL, у меня есть некоторые сомнения.


Мой второй вопрос: учитывая, что у меня есть библиотеки Oracle и библиотеки SAS, каковы отношения между индексами, определенными в ORACLE, и индексами, определенными в SAS?

Следующий запрос выполняется очень быстро, поскольку таблица была проиндексирована в базе данных Oracle:

PROC SQL;
  SELECT * FROM ORACLELIB.MY_TABLE
  WHERE RELATION_ID = 1097;
QUIT;

Но если я попытаюсь выполнить простое внутреннее соединение с 1 столбцом, 1 наблюдением, индексированной таблицей, расположенной в моей WORK библиотеке, запрос займет очень много времени:

data TEST;
   input RELATION_ID;
   datalines;
   1097
;

proc datasets library=WORK;
   modify TEST;
      index create RELATION_ID;
run;

PROC SQL;
  SELECT * FROM ORACLELIB.MY_TABLE t1
  INNER JOIN TEST t2
  ON t1.RELATION_ID = t2.RELATION_ID;
QUIT;

Это тоже медленно:

PROC SQL;
  SELECT * FROM ORACLELIB.MY_TABLE t1
  WHERE RELATION_ID IN (SELECT RELATION_ID FROM TEST);
QUIT;

Я также попытался создать свою тестовую таблицу в библиотеке оракула, которая не находится на том же сервере оракула):

data ORACLELIB2.TEST;
   input RELATION_ID;
   datalines;
   1097
;

Это кажется таким же медленным (в этом случае я не могу его индексировать из-за ограничений, но это только одно наблюдение).


Это приводит к моему последнему вопросу: что я могу сделать, чтобы это соединение работало так быстро, как должно?


Дополнительные примечания:

У меня есть 3 сервера:

  • основной сервер ORACLE, на котором я не могу писать, содержащий библиотеку с MY_TABLE
  • Еще один сервер ORACLE, на котором я могу писать.
  • Сервер SAS, где я могу писать

Моим основным использованием будут запросы следующего типа:

CREATE TABLE NEWTABLE AS
SELECT *columns* FROM smaller_table t1 LEFT JOIN MY_TABLE t2
ON t1.RELATION_ID = t2.RELATION_ID and t1.other_col = t2.other col
WHERE *additional restrictions on t2*;

person Moody_Mudskipper    schedule 29.05.2018    source источник


Ответы (3)


Вам следует изучить вариант SASTRACE= (9.2 docs), который будет регистрировать, что делает механизм удаленной библиотеки. Я ожидал, что движок выполнит собственную неявную передачу простых соединений. Механизм автоматически преобразует некоторые функции SAS и предложения группировки в эквиваленты на стороне Oracle.

Если вы не можете заставить серверную часть работать ожидаемым образом быстро, для небольших наборов идентификаторов {пару тысяч}) рассмотрите возможность создания кода IN списка и посмотрите, будет ли он работать лучше.

proc sql noprint;
  select relation_id into :id_list separated by ',' from test;

  SELECT * FROM ORACLELIB.MY_TABLE t1
  WHERE RELATION_ID IN (&id_list);
quit;

Если идентификаторы являются символьными, генератор кода должен будет quote() значения в выборе.

person Richard    schedule 29.05.2018
comment
Это хороший момент, Ричард, я думал об этой стратегии, используя IN для предварительной фильтрации моей таблицы перед присоединением, но пара тысяч - это мало, я обычно играю со значениями в диапазоне от 10 до 300 тысяч. - person Moody_Mudskipper; 29.05.2018
comment
Будет ли select distinct relation_id into ... более эффективным? - person Moody_Mudskipper; 29.05.2018
comment
Я предположил, что таблица селекторов поиска (тест) содержит только отдельный идентификатор отношения. Определенно более эффективно, если тест содержит дубликаты — аналогично, альтернативные решения, включающие загрузку тестовых данных, будут иметь передовую практику загрузки в виде среза столбца, содержащего только отдельные отношения_идентификаторы. - person Richard; 29.05.2018

Касательно

Если я перемещу свою тестовую таблицу в библиотеку оракула, эти запросы все равно будут медленными (в этом случае я не могу ее индексировать из-за ограничений, но это только одно наблюдение).

Как вы перешли на Oracle? p.s. ORACLELIB не является действительным SAS libref, поэтому я предполагаю, что это псевдокод.

Взгляните на SAS/ACCESS® 9.4 для реляционных баз данных: справочник , девятое издание, пример: создание и объединение постоянной и временной таблиц.

В примере используется опция dbmstemp=yes libname и

показано, как использовать эту опцию для создания постоянной и временной таблицы, а затем объединить их в запросе.

Вы также можете загрузить данные тестовой таблицы в таблицу TEMP сеанса подключения, а затем выбрать набор результатов с помощью сквозного SQL-запроса. Сквозной запрос позволит вам иметь полный контроль над запросом, включая определенные функции хоста (например, подсказки Oracle, которые принудительно используют индекс), которые может не использовать механизм удаленной библиотеки SAS.

Независимо от способа соединения межсистемная передача, вероятно, является одним из наиболее трудоемких аспектов. Вы хотите найти способ, который выполняет наибольшую работу при наименьшем количестве передач.

person Richard    schedule 29.05.2018
comment
Да, это псевдокод, я переименовал таблицы и библиотеки, чтобы быть уверенным, что не раскрываю ничего, чего не должен, я создаю свою примерную таблицу в библиотеке оракула следующим образом: data ORACLELIB2.TEST; input RELATION_ID; datalines; 1097 ; - person Moody_Mudskipper; 29.05.2018
comment
Смотрите мой, надеюсь, проясненный вопрос, теперь я покопаюсь в ваших предложениях и посмотрю, как я могу их использовать, спасибо. - person Moody_Mudskipper; 29.05.2018

На самом деле есть 3 способа создать индекс в SAS:

  1. Proc Datasets/Modify/Index Create
  2. параметр набора данных (index=) и
  3. Proc SQL/ Создать индекс

Насколько мне известно, первые два — единственный способ указать параметры в дополнение к Unique.

Ответ на вопрос, как ускорить соединение, скорее всего, будет заключаться в сочетании (сквозной) обработки в вашей Oracle БД и предварительной/постобработки в SAS. И может включать или не включать создание индексов.

Это будет зависеть от:

  • а) где находятся ваши данные и размер(ы) данных, и
  • б) чего вы пытаетесь достичь с точки зрения результата.

Можете ли вы предоставить больше информации?

РЕДАКТИРОВАТЬ: хорошо, большая таблица в Oracle, маленькая таблица в SAS, маленькая таблица является драйвером выходных строк

Не зная точных деталей, причина, по которой ваш запрос был медленным, была связана не с индексами, а скорее с тем фактом, что вы «вытягивали» данные из большой таблицы Oracle, чтобы удовлетворить запрос.

Легко исправить, согласно последнему предложению обновленного ответа Ричарда: перенести небольшую таблицу в Oracle...

Чтобы было понятно, перенесите маленькую таблицу в Oracle, запустите там запрос и сохраните там результаты. При необходимости используйте соответствующее средство передачи для экспорта данных в SAS...

person Peter    schedule 29.05.2018
comment
Дополнительным способом является функция SCL SAS/AF ICREATE - person Richard; 29.05.2018
comment
а) данные размером 50 миллионов строк находятся на удаленном сервере где-то в секретном месте посреди Германии :) - person Moody_Mudskipper; 29.05.2018
comment
б) Это очень важная таблица, нам нужно сделать много объединений в 1-3 столбцах этих таблиц, все из которых хорошо проиндексированы в базе данных оракула. Есть также другие таблицы, обычно менее большие, на которых я хотел бы использовать эти индексы. - person Moody_Mudskipper; 29.05.2018
comment
Итак, чтобы быть ясным в качестве ответа на мой первый вопрос, все эти методы индексации эквивалентны их вводу? (несмотря на то, что некоторые поддерживают больше функций) - person Moody_Mudskipper; 29.05.2018
comment
@Moody_Mudskipper: да, методы индексирования одинаковы при вводе. Что касается ваших ответов, удаленный сервер — это Oracle, а важная таблица и другие таблицы находятся на другом сервере в SAS или в каком-то другом формате, верно? - person Peter; 29.05.2018
comment
Правка и исправление. Данные находятся на сервере ORACLE и на другом сервере SAS. У меня есть большие таблицы, в которых я надеюсь выполнять соединения с каждой стороны, но моя текущая проблема относится к таблицам Oracle. - person Moody_Mudskipper; 29.05.2018
comment
в порядке. можете ли вы уточнить: текущая проблема относится к таблицам Oracle - я думаю, вы имеете в виду, что проблема заключается в объединении данных из двух сред, верно? - person Peter; 29.05.2018
comment
также: какая таблица является драйвером требуемого вывода/строк? например, вы обновляете большую таблицу значениями из определенных строк в маленькой таблице? или все наоборот? - person Peter; 29.05.2018
comment
Это относится к таблицам Oracle в том смысле, что моя большая таблица, которую я назвал MY_TABLE, находится в библиотеке Oracle. Другая таблица, которую я хочу использовать в операции join, находится либо в библиотеке SAS (просто WORK в моем примере), либо в другой библиотеке Oracle (скажем, ORACLELIB2). - person Moody_Mudskipper; 29.05.2018
comment
re 'какая таблица является драйвером требуемых выходных данных/строк', я думаю, что обычно это будет smaller_table left join MY_TABLE с дополнительными фильтрами на MY_TABLE - person Moody_Mudskipper; 29.05.2018
comment
@Moody_Mudskipper: см. Чтобы уточнить... в моем ответе - person Peter; 29.05.2018
comment
Извините за то, что туда-сюда, я нахожу больше информации по мере того, как мы повторяем. Бывает, что библиотеки оракулов, в которых я могу писать, находятся на другом сервере, поэтому ваша точка зрения о копируемых данных остается в силе. Я думаю, что мне, возможно, придется просто скопировать полную большую таблицу в SAS и переиндексировать ее. - person Moody_Mudskipper; 29.05.2018