HASHBUCKET() con 20 bits y conversiones a INTEGER.

Un colega (y tocayo) me escribió un “mail” en el que me decía que las “queries” que puse en los artículos “¿Cuándo recopilaste estadísticas por última vez (en Teradata)?” le estaban fallando. Me indicaba que los estaba ejecutando en un Teradata 13.

En efecto, escribí los artículos con ejemplos tomados de un Teradata 12 que venía de un “upgrade” de una V6R2, así que probé yo mismo:

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT * FROM DBC.DBCINFO;

 *** Query completed. 3 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

InfoKey                        InfoData
------------------------------ --------------------------------------------
RELEASE                        13.10.00.10
VERSION                        13.10.00.14
LANGUAGE SUPPORT MODE          Standard

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT
           c.databasenamei (VARCHAR(30)) "DatabaseName",
           b.tvmnamei      (VARCHAR(30)) "TableName",
           d.fieldname     (VARCHAR(30)) "ColumnName",
           a.IndexNumber                 "ColumnGroup",
           HASHBUCKET( CAST(SUBSTR(a.IndexStatistics,2,1) ||
                            SUBSTR(a.IndexStatistics,1,1) ||
                            '0000'XB AS BYTE(4)) ) "AÑO",
           HASHBUCKET( CAST('00'XB ||
                            SUBSTR(a.IndexStatistics,3,1) ||
                            '0000'XB AS BYTE(4)) ) (FORMAT '99') "MES",
           HASHBUCKET( CAST('00'XB ||
                            SUBSTR(a.IndexStatistics,4,1) ||
                            '0000'XB AS BYTE(4)) ) (FORMAT '99') "DÍA",
           HASHBUCKET( CAST('00'XB ||
                            SUBSTR(a.IndexStatistics,5,1) ||
                            '0000'XB AS BYTE(4)) ) (FORMAT '99') "HORA",
           HASHBUCKET( CAST('00'XB ||
                            SUBSTR(a.IndexStatistics,6,1) ||
                            '0000'XB AS BYTE(4)) ) (FORMAT '99') "MINUTO",
           HASHBUCKET( CAST('00'XB ||
                            SUBSTR(a.IndexStatistics,7,1) ||
                            '0000'XB AS BYTE(4)) ) (FORMAT '99') "SEGUNDO"
      FROM
          dbc.Indexes a,
          dbc.Indexes aa,
          dbc.tvm b,
          dbc.dbase c,
          dbc.tvfields d
    WHERE a.tableid = aa.tableid
      AND a.IndexNumber = aa.IndexNumber
      AND a.tableid = b.tvmid
      AND b.tablekind = 'T'
      AND b.databaseid = c.databaseid
      AND a.IndexStatistics IS NOT NULL
      AND b.TVMid = d.tableid
      AND aa.fieldid = d.fieldid;

 *** Query completed. 2 rows found. 10 columns returned.
 *** Total elapsed time was 1 second.

DatabaseName TableName ColumnName ColumnGroup   AÑO MES DÍA  HORA MINUTO SEGUNDO
------------ --------- ---------- ----------- ----- --- ---- ---- ------ -------
CARLOS       PRUEBA01  id_n               129 32192  **   80   **     **      **
CARLOS       PRUEBA01  C_TXT              129 32192  **   80   **     **      **

Y, claro, la conversión a fecha (date) fallaba.

Después de unos minutos de estupor, busqué en la documentación de HASHBUCKET():

2.5 Hash Bucket Expansion

Teradata Database 12.0 supports either 65,536 or 1,048,576 hash buckets for a system. The larger number of buckets primarily benefits systems with thousands of AMPs, but there is no disadvantage to using the larger number of buckets on smaller systems.
On systems with:

65,536 hash buckets, the system uses 16 bits of the 32-bit RowHash to index into the hash map.
1,048,576 hash buckets, the system uses 20 bits of the 32-bit RowHash as the index.

Y, como era de esperar, ahí estaba la madre del cordero. Si el sistema está configurado para tabajar con 1.048.576 hash buckets se utilizan 20 bits, en lugar de los 16 bits utilizados en el sistema que yo había empleado para los ejemplos.

La respuesta, como siempre, está en as matemáticas, ya que hay que tener en cuenta esos cuatro bits extra (SHR –shift right– ¿recuerda alguien el ensamblador?): para utilizar la conversión de BYTE a INTEGER en estos sistemas hay que dividir por 16 (cuatro SHR: 2,4,8,16).

 BTEQ -- Enter your SQL request or BTEQ command:

SELECT
           c.databasenamei (VARCHAR(30)) "DatabaseName",
           b.tvmnamei      (VARCHAR(30)) "TableName",
           d.fieldname     (VARCHAR(30)) "ColumnName",
           a.IndexNumber                 "ColumnGroup",
           HASHBUCKET( CAST(SUBSTR(a.IndexStatistics,2,1) ||
                            SUBSTR(a.IndexStatistics,1,1) ||
                            '0000'XB AS BYTE(4)) )/16 "AÑO",
           HASHBUCKET( CAST('00'XB ||
                            SUBSTR(a.IndexStatistics,3,1) ||
                            '0000'XB AS BYTE(4)) )/16 (FORMAT '99') "MES",
           HASHBUCKET( CAST('00'XB ||
                            SUBSTR(a.IndexStatistics,4,1) ||
                            '0000'XB AS BYTE(4)) ) (FORMAT '99') "DÍA",
           HASHBUCKET( CAST('00'XB ||
                            SUBSTR(a.IndexStatistics,5,1) ||
                            '0000'XB AS BYTE(4)) )/16 (FORMAT '99') "HORA",
           HASHBUCKET( CAST('00'XB ||
                            SUBSTR(a.IndexStatistics,6,1) ||
                            '0000'XB AS BYTE(4)) )/16 (FORMAT '99') "MINUTO",
           HASHBUCKET( CAST('00'XB ||
                            SUBSTR(a.IndexStatistics,7,1) ||
                            '0000'XB AS BYTE(4)) )/16 (FORMAT '99') "SEGUNDO"
      FROM
          dbc.Indexes a,
          dbc.Indexes aa,
          dbc.tvm b,
          dbc.dbase c,
          dbc.tvfields d
    WHERE a.tableid = aa.tableid
      AND a.IndexNumber = aa.IndexNumber
      AND a.tableid = b.tvmid
      AND b.tablekind = 'T'
      AND b.databaseid = c.databaseid
      AND a.IndexStatistics IS NOT NULL
      AND b.TVMid = d.tableid
      AND aa.fieldid = d.fieldid;

 *** Query completed. 2 rows found. 10 columns returned.
 *** Total elapsed time was 1 second.

DatabaseName TableName ColumnName ColumnGroup AÑO  MES DÍA HORA MINUTO SEGUNDO
------------ --------- ---------- ----------- ---- --- --- ---- ------ -------
CARLOS       PRUEBA01  id_n               129 2012  07  80   08     56      52
CARLOS       PRUEBA01  C_TXT              129 2012  07  80   08     56      52

Así pues, para sistemas con 1.048.576 hash buckets la conversión de BYTE a ‘smallints’ deben utilizar esta división para que todo funcione OK.

Saludos.

Carlos.

Una respuesta a HASHBUCKET() con 20 bits y conversiones a INTEGER.

  1. […] Nota importante: Esta entrada se escribió tomando como base un sistema con 65.536 hash buckets. Si tu sistema está configurado para 1.048.576 hash buckets debes leer esto. […]

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: