HASH-MERGE vs Lookups. Octubre 12, 2011 Moisés Ramírez Flores Sr. Statistical Programmer Pharmanet/i3
Agenda Introducción Hash Step. Como realizar un hash merge Preguntas
Introducción Como programadores SAS constantemente necesitamos realizar varios cruces de dos o mas tablas usando una tabla asociada crosswalk o Table-lookup lo que se conoce como many-to-many join. Muchas veces usando un PROC SQL o el tradicional merge-sortmerge method, el cual es considerablemente más lento. Existen otras técnicas que pueden ofrecernos ventajas en conveniencia y rendimiento. Desde el lanzamiento de SAS 9 dos tipos de objetos están disponibles para su uso en el Data Step: Has-Tables y Hash iterator
HAS-TABLES No es un concepto nuevo. C++, Microsoft.NET y lenguajes como C# y VB lo utilizan. Aunque es un concepto desconocido en SAS. Una función hash, es cualquier algoritmo o rutina que realice un mapeo entre un gran conjunto de datos y un pequeño conjunto llamado Table_lookup. Hoy en día cualquier método basado en técnicas de dirección dirigida son referidos como hashing. El concepto en SAS esta basado en arreglo temporal en memoria que funciona como un table-lookup.
Dirección dirigida
Dirección dirigida (arreglo llave) Element 1 2 3 4 5 6 7 8 9 Value a b C d e f g h I
Entendiendo el Hash Data Step Ejemplo: Tenemos los siguientes conjuntos
Hash Data Step
Sql-Merge: Proc sql ; Quit ; Create view PapersAndTheirAuthors as select * from Paper natural right join ( select * from PaperAuthor natural left join Author ) ; Con un natural join in Proc sql.
SORT, SORT, MERGE, RESORT, SORT, AND THEN MERGE AGAIN: Proc sort data=paper ; By PaperKey ; Run ; Proc sort data=paperauthor ; By PaperKey ; Run ; Data PaperWithAuthorKey ; Merge Paper PaperAuthor( in=inpaperauthor ); By PaperKey ; If inpaperauthor ; Run ; Proc sort data=paperwithauthorkey ; By AuthorKey ; Run ; Proc sort data=author ; By AuthorKey ; Run ; Data PapersAndTheirAuthors ; Merge PaperWithAuthorKey( in=inpaperwithauthorkey ) Author ; By AuthorKey ; If inpaperwithauthorkey ; Run ;
Hash Data Step Data PapersAndTheirAuthors / view=papersandtheirauthors ; Set RandomPaperAuthor ; 1 If ( _N_ eq 1 ) then do ; If 0 then set RandomPaper RandomAuthor ; 1 Declare hash p( dataset:'randompaper', hashexp:16 ) ; Primero especificamos las propiedades de las variables presentes p.definekey('paperkey') en ambas ; tablas (Length, label, etc.) para no tener que p.definedata( codificarlas all:'yes' a mano. ) ; p.definedone() ; Declare hash a( dataset:'randomauthor', hashexp:16 ) ; a.definekey('authorkey') ; a.definedata( all:'yes' ) ; a.definedone() ; End ; If not p.find() ; If not a.find() ; Run ; Las Tablas están en orden aleatorio
Hash Data Step Data PapersAndTheirAuthors / view=papersandtheirauthors ; Set RandomPaperAuthor ; If ( _N_ eq 1 ) then do ; If 0 then set RandomPaper RandomAuthor ; 2 Declare hash p( dataset:'randompaper', hashexp:16 ) ; End ; p.definekey('paperkey') ; Después declaramos nuestra hash table utilizando el enunciado p.definedata( Declare all:'yes' ) seguido ; de la palabra hash. p.definedone() ; Entre paréntesis deben de existir dos argumentos, Declare hash a( dataset:'randomauthor', hashexp:16 ) ; Dataset. a.definekey('authorkey') El nombre del ; conjunto del que obtendremos la información. a.definedata( all:'yes' ) ; a.definedone() ; HashExp. Que especifica el tamaño de la tabla interna del objeto hash el cual es 2 elevado a la n y el máximo permitido es 16. If not p.find() ; If not a.find() ; Run ; Las Tablas están en orden aleatorio 2
Hash Data Step Data PapersAndTheirAuthors / view=papersandtheirauthors ; Set RandomPaperAuthor ; If ( _N_ eq 1 ) then do ; If 0 then set RandomPaper RandomAuthor ; Declare hash p( dataset:'randompaper', hashexp:16 ) ; 3 p.definekey('paperkey') ; 3 p.definedata( all:'yes' ) ; Utilizamos el enunciado definekey para declarar nuestras variables p.definedone() llave, ; si son más de una la podemos declarar simplemente Declare hash a( separándolas dataset:'randomauthor' por una, hashexp:16 coma. ) ; a.definekey('authorkey') ; a.definedata( all:'yes' ) ; a.definedone() ; End ; If not p.find() ; If not a.find() ; Run ; Las Tablas están en orden aleatorio
Hash Data Step Data PapersAndTheirAuthors / view=papersandtheirauthors ; Set RandomPaperAuthor ; If ( _N_ eq 1 ) then do ; If 0 then set RandomPaper RandomAuthor ; Declare hash p( dataset:'randompaper', hashexp:16 ) ; p.definekey('paperkey') ; 4 p.definedata( all:'yes' ) ; 4 p.definedone() ; Con el enunciado definedata declaramos que variables iran a nuestro Declare hash cruce a( de dataset:'randomauthor' tablas, otra vez si, son hashexp:16 más de ) ; una la podemos a.definekey('authorkey') declarar simplemente ; separándolas por una coma. a.definedata( all:'yes' ) ; a.definedone() ; End ; If not p.find() ; If not a.find() ; Run ; Las Tablas están en orden aleatorio
Hash Data Step Data PapersAndTheirAuthors / view=papersandtheirauthors ; Set RandomPaperAuthor ; If ( _N_ eq 1 ) then do ; If 0 then set RandomPaper RandomAuthor ; Declare hash p( dataset:'randompaper', hashexp:16 ) ; p.definekey('paperkey') ; p.definedata( all:'yes' ) ; 5 p.definedone() ; 5 Declare hash a( dataset:'randomauthor', hashexp:16 ) ; Una vez que las propiedades han sido definidas cerramos la misma a.definekey('authorkey') con el enunciado ; definedone. a.definedata( all:'yes' ) ; a.definedone() ; End ; If not p.find() ; If not a.find() ; Run ; Las Tablas están en orden aleatorio
Hash Data Step Data PapersAndTheirAuthors / view=papersandtheirauthors ; Set RandomPaperAuthor ; If ( _N_ eq 1 ) then do ; If 0 then set RandomPaper RandomAuthor ; Declare hash p( dataset:'randompaper', hashexp:16 ) ; p.definekey('paperkey') ; p.definedata( all:'yes' ) ; p.definedone() ; Declare hash a( dataset:'randomauthor', hashexp:16 ) ; a.definekey('authorkey') ; a.definedata( all:'yes' ) ; 5 a.definedone() ; 5 End ; Run ; If not p.find() ; Repetimos estos mismos pasos para la otra tabla. If not a.find() ; Las Tablas están en orden aleatorio
Hash Data Step Data PapersAndTheirAuthors / view=papersandtheirauthors ; Set RandomPaperAuthor ; If ( _N_ eq 1 ) then do ; If 0 then set RandomPaper RandomAuthor ; Declare hash p( dataset:'randompaper', hashexp:16 ) ; p.definekey('paperkey') ; p.definedata( all:'yes' ) ; p.definedone() ; Declare hash a( dataset:'randomauthor', hashexp:16 ) ; a.definekey('authorkey') ; a usar el a.definedata( in= dataset all:'yes' option ) ; para quedarte únicamente con las El If not p.find() and If not a.find() statements son equivalentes observaciones a.definedone() que contribuyen ; a ambos datasets como en el método tradicional de sort-sort-merge-sort-sort-merge. End ; 6 If not p.find() ; If not a.find() ; 6 Run ; Las Tablas están en orden aleatorio
Hash Data Step Data PapersAndTheirAuthors / view=papersandtheirauthors ; Set RandomPaperAuthor ; 1 If ( _N_ eq 1 ) then do ; If 0 then set RandomPaper RandomAuthor ; 1 Declare hash p( dataset:'randompaper', hashexp:16 ) ; p.definekey('paperkey') ; 3 p.definedata( all:'yes' ) ; 4 p.definedone() ; 5 Declare hash a( dataset:'randomauthor', hashexp:16 ) ; a.definekey('authorkey') ; a.definedata( all:'yes' ) ; a.definedone() ; 2 End ; If not p.find() ; If not a.find() ; 6 Run ; Las Tablas están en orden aleatorio
Mi propio ejemplo
Performance
Performance
Paper 107-2008 %HASHMERGE A Macro to Hash When It Can, Merge When It Can t Gregg P. Snell, Data Savant Consulting, Shawnee, KS 1. IS THERE ENOUGH MEMORY TO HASH?. 2. PRODUCE MATCH-MERGE CODE. 3. PRODUCE HASH-MERGE CODE. 4. CREATE THE MACRO TO LOOK LIKE STANDARD MATCH-MERGE CODE
Tabla de Pros y Contras Método Pros Contras SET con KEY= Bajo costo de memoria Crear índices Lento acceso I/O Merge con BY Proc SQL Bajo costo de memoria Rápido acceso a varios data sets por medio del input Rápido acceso y cruce on the air de varias tablas Uso común en otros lenguajes. Los datos de entrada deben de estar ordenados y preferentemente con un index asociado. No tienes las ventajas de un input stament para la lectura de diferentes tipos de datos Funciones estadísticas limitadas
Tabla de Pros y Contras Método Pros Contras Hash Objects Rápido cruce de observaciones que contienen una llave en particular. La llave puede estar compuesta de multuples valores de tipo carácter o numerico. Todas las ventajas de un data step. Las observaciones se guardan en memoria. Usar un arreglo temporal es mas rapido que usar el arreglo del hash object. El arreglo del hash object utiliza mas memoria que uno equivalente normal. No hay necesidad de sortear o indexar los datos.
Conclusión El método de Hash-merge es una herramienta adicional que SAS nos proporciona, la cual bajo ciertas circunstancias nos permite realizar mejor y de manera mas eficiente nuestros cruces de tablas.
Preguntas
Gracias Moisés Ramírez Flores Sr. Statistical Programmer Pharmanet/i3 Copyright 2011, SAS Copyright Institute Inc. 2011, All SAS rights Institute reserved. Inc. All rights reserved.