En el ejemplo anterior, el esquema se deduce utilizando reflexión. También podemos especificar mediante programación el esquema del dataset. Esto es útil cuando las clases personalizadas no se pueden definir con anticipación porque la estructura de los datos está codificada en una cadena.
El siguiente ejemplo de código muestra cómo especificar el esquema utilizando las clases de tipo de datos StructType, StringType y StructField.
//
// Programmatically Specifying the Schema
//
// Create SQLContext from the existing SparkContext.
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
// Create an RDD
val rddCustomers = sc.textFile(“/home/emanuel/eje.csv”)
// The schema is encoded in a string
val schemaString = “customer_id name city state zip_code”
// Import Spark SQL data types and Row.
import org.apache.spark.sql._
import org.apache.spark.sql.types._;
// Generate the schema based on the string of schema
val schema = StructType(schemaString.split(“ “).map(fieldName => StructField(fieldName, StringType, true)))
// Convert records of the RDD (rddCustomers) to Rows.
val rowRDD = rddCustomers.map(_.split(“,”)).map(p => Row(p(0).trim,p(1),p(2),p(3),p(4)))
// Apply the schema to the RDD.
val dfCustomers = sqlContext.createDataFrame(rowRDD, schema)
// Register the DataFrames as a table.
dfCustomers.registerTempTable(“customers”)
// SQL statements can be run by using the sql methodsprovided by sqlContext.
val custNames = sqlContext.sql(“SELECT name FROM customers”)
// The results of SQL queries are DataFrames and support all the normal RDD operations.
// The columns of a row in the result can be accessed by ordinal.
custNames.map(t => “Name: “ + t(0)).collect().foreach(println)
// SQL statements can be run by using the sql methods provided by sqlContext.
val customersByCity = sqlContext.sql(“SELECT name,zip_code FROM customers ORDER BY zip_code”)
// The results of SQL queries are DataFrames and support all the normal RDD operations.
// The columns of a row in the result can be accessed by ordinal.
customersByCity.map(t => t(0) + “,” + t(1)).collect().
foreach(println)
También podemos cargar los datos de otras fuentes de datos como archivos de datos JSON, tablas Hive o incluso tablas de bases de datos relacionales que utilizan la fuente de datos JDBC.
Spark SQL proporciona una agradable interfaz SQL para interactuar con datos que se cargan desde diversas fuentes de datos, utilizando la conocida sintaxis de consulta SQL.
Esto es especialmente útil para miembros de proyectos no técnicos, como analistas de datos y DBA.
Translate
domingo, 6 de mayo de 2018
Ejemplo de Apache Spark Sql
Para este ejemplo, cargaremos datos de clientes de un archivo de texto y crearemos un objeto DataFrame a partir del conjunto de datos. Entonces podemos ejecutar las funciones de DataFrame como consultas específicas para seleccionar los datos.
Veamos el archivo customers.txt.
100,John Smith, Austin, TX, 78727
200,Joe Johnson, Dallas, TX, 75201
300,Bob Jones, Houston, TX, 77028
400,Andy Davis, San Antonio, TX, 78227
500,James Williams, Austin, TX, 78727
El siguiente código muestra los comandos Spark SQL que podemos ejecutar en la consola del shell Spark.
// Create the SQLContext first from the existing Spark Context
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
// Import statement to implicitly convert an RDD to a DataFrame
import sqlContext.implicits._
// Create a custom class to represent the Customer
case class Customer(customer_id: Int, name: String, city: String, state: String, zip_code: String)
// Create a DataFrame of Customer objects from the data set text file.
val dfCustomers = sc.textFile(“/home/emanuel/eje.csv”).map(_.split(“,”)).map(p => Customer(p(0).trim.toInt, p(1), p(2), p(3), p(4))).toDF()
// Register DataFrame as a table.
dfCustomers.registerTempTable(“customers”)
// Display the content of DataFrame
dfCustomers.show()
// Print the DF schema
dfCustomers.printSchema()
// Select customer name column
dfCustomers.select(“name”).show()
// Select customer name and city columns
dfCustomers.select(“name”, “city”).show()
// Select a customer by id
dfCustomers.filter(dfCustomers(“customer_id”).equalTo(500)).show()
// Count the customers by zip code
dfCustomers.groupBy(“zip_code”).count().show()
Veamos el archivo customers.txt.
100,John Smith, Austin, TX, 78727
200,Joe Johnson, Dallas, TX, 75201
300,Bob Jones, Houston, TX, 77028
400,Andy Davis, San Antonio, TX, 78227
500,James Williams, Austin, TX, 78727
El siguiente código muestra los comandos Spark SQL que podemos ejecutar en la consola del shell Spark.
// Create the SQLContext first from the existing Spark Context
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
// Import statement to implicitly convert an RDD to a DataFrame
import sqlContext.implicits._
// Create a custom class to represent the Customer
case class Customer(customer_id: Int, name: String, city: String, state: String, zip_code: String)
// Create a DataFrame of Customer objects from the data set text file.
val dfCustomers = sc.textFile(“/home/emanuel/eje.csv”).map(_.split(“,”)).map(p => Customer(p(0).trim.toInt, p(1), p(2), p(3), p(4))).toDF()
// Register DataFrame as a table.
dfCustomers.registerTempTable(“customers”)
// Display the content of DataFrame
dfCustomers.show()
// Print the DF schema
dfCustomers.printSchema()
// Select customer name column
dfCustomers.select(“name”).show()
// Select customer name and city columns
dfCustomers.select(“name”, “city”).show()
// Select a customer by id
dfCustomers.filter(dfCustomers(“customer_id”).equalTo(500)).show()
// Count the customers by zip code
dfCustomers.groupBy(“zip_code”).count().show()
Apache Spark Sql - JDBC Data Source
Spark sql contiene un origen de datos jdbc. Con él podemos leer una base de datos relacional. Este enfoque es preferible al uso de JdbcRDD porque el origen de datos devuelve los resultados como un DataFrame que puede procesarse en Spark SQL o mezclarse con datos de otras fuentes de datos.
Veamos un ejemplo:
import org.apache.spark.sql.SQLContext
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
val url = "jdbc:mysql://127.0.0.1:3306/amarokdb"
val df = spark.read.format("jdbc").option("url", url).option("dbtable", "albums").option("user", "root").option("password","pass").load()
df.printSchema() // Looks the schema of this DataFrame.
df.show()
df.count()
jueves, 3 de mayo de 2018
Apache Spark Sql
Como habíamos dicho en un ambiente Spark SQL, los 2 componentes más importantes son el DataFrame y el SQLContext.
DataFrame: Un dataframe es una colección de datos distribuida organizada dentro de nombres de columnas. Esto basado en el concepto de dataframe del Lenguaje R y similar al concepto de tablas de las base de datos relacionales.
SchemaRDD, que se encuentra en versiones anteriores de Spark SQL API y se ha renombrado como DataFrame.
DataFrames puede ser convertido en un RDDs, por medio de un método de RDD, el RDD resultante tiene las filas del DataFrames.
Los DataFrames pueden ser creados dados los siguientes origenes de datos:
- RDDs existentes
- un archivo estructurado
- un Json
- una tabla HIVE
- y una base de datos externa.
Spark SQL y DataFrame APIs esta disponible en Scala, Java, Python y R.
Además de DataFrame, Spark también proporciona la API Dataset. Un Dataset es una colección distribuida de datos similar a los RDD pero que utiliza un codificador para serializar los objetos. La API Dataset está disponible en Scala y Java. Spark SQL admite métodos para convertir RDD existentes en conjuntos de datos.
SQLContext: Spark SQL proporciona SQLContext para encapsular toda la funcionalidad relacional en Spark. Se crea el SQLContext a partir del SparkContext existente, veamos un ejemplo:
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
También hay HiveContext, que proporciona un superconjunto de la funcionalidad proporcionada por SQLContext. Se puede usar para escribir consultas usando el analizador HiveQL y para leer datos de tablas de Hive.
Notemos que no necesitamos un entorno Hive existente para usar HiveContext en los programas Spark.
miércoles, 2 de mayo de 2018
Lecciones aprendidas instalando Hadoop en un cluster
Instale un cluster de hadoop y tuve unos problemas, 2 para hacer exactos:
No se si hice bien, pero los puse en workers y anda.
Alguien tiene idea si esto cambio?
- Use linux Ubuntu, y por algún motivo te pone como nombre de servidor en /etc/hosts el ip 127.0.1.1 eso trae muchos quilombos no se porque. Comenta la linea y listo
- Y luego, tuve problema porque en tutorial, decia que tenia que poner los slaves (o esclavos) y el archivo se llamaba workers
No se si hice bien, pero los puse en workers y anda.
Alguien tiene idea si esto cambio?
martes, 1 de mayo de 2018
Machine Learning Yearning
No me acuerdo cuando pero hice un curso de machine learning en coursera, bueno el profesor de este curso Andrew Ng esta sacando un libro. Por lo tanto ha compartido unos capítulos y los manda por mail.
Y yo quiero compartirlos con ustedes.
Dejo los links:
https://gallery.mailchimp.com/dc3a7ef4d750c0abfc19202a3/files/0e40554e-8eae-416c-85dc-9bdaf433347a/Ng_MLY01.pdf
https://gallery.mailchimp.com/dc3a7ef4d750c0abfc19202a3/files/91f11a9a-09d8-475f-9cfa-6d0e98e17b5e/Ng_MLY02.pdf
domingo, 29 de abril de 2018
Los 5 lenguajes más odiados
Lei un articulo sobre los 5 lenguajes más odiados y en parte le doy la razon en parte no.
Los lenguajes son :
- Perl
- Delphi
- VBA
- Objective-C
- PHP
Voy a empezar con las criticas, primero Delphi no es un lenguaje de programación el lenguaje es object pascal, que como lenguaje no es tan malo, en realidad me resulta mejor que c++.
Segundo, no se como han listado los lenguajes, porque hay muchos que son más odiables como COBOL o el lenguaje que usaba Clarion.
Lo positivo es que coincido con casi todos, Perl es inhumano e inentendible, VBA y Objective-C nunca los pude aprender o programar decentemente.
Pero banco a muerte a Object Pascal y a PHP. Me han dado de comer y pasamos ratos agradables juntos. En mi opinion, se podría hacer un lindo lenguaje totalmente orientado a objeto como Ruby o Scala inspirado en Object Pascal y la rompería.
Como leerán esto es solo una opinión, y a ustedes que lenguaje no les gusta?
Azure Sphere, el sistema operativo de Microsoft con kernel Linux
A esta altura no me sorprende nada, ya el carton esta lleno. Microsoft presento un sistema operativo con kernel Linux, lo llama Azure Sphere y el objetivo principal es que sea un sistema operativo para internet de las cosas.
Según rumores el principal motivo de utilizar Linux es la seguridad. No existe nada más seguro que un kernel linux.
Dejo un video:
Dejo link: https://www.microsoft.com/en-us/azure-sphere/
jueves, 26 de abril de 2018
Google abre convocatoria para becas de investigación en Latinoamérica: Lara
Quiero hacerme eco de esta noticia. Por las dudas si un pichon de investigador me lee.
Google lanzó la quinta versión de su programa de becas de investigación para Latinoamérica.
El gigante de internet lanzó recientemente la quinta versión de su programa de becas Latin America Research Awards (Lara por sus siglas en inglés). Este programa tiene como objetivo principal solucionar algunos de los desafíos actuales a través de la tecnología. La convocatoria estará abierta hasta el próximo 25 de mayo de 2018 y solo podrán participar las personas que actualmente sean estudiantes de maestría o doctorado en Latinoamérica, así como aquellos que se desempeñen como profesores o tutores.
Si te interesa, tenes que dejar de leer este blog y leer este :
https://latam.googleblog.com/2018/04/registrate-en-lara-2018-premios-de-investigacion-de-google-para-america-latina.html
Apache Spark Sql
Spark Sql es parte de Spark y permite consultar datos en Spark, utilizando un lenguaje estructurado similar a SQL. Podemos exportar datos a xml, json, etc.
Spark Sql nos permite consultar archivos batch, conjunto de datos Json o tablas Hive. Spark Sql trae características muy útiles y en las ultimas versiones ha agregado importantes mejoras en las que podemos nombrar:
DataFrames: es una abstracción que permite que funcione como SQL query engine distribuido.
Una Api de origen de datos (datasource) que permite conectarse con orígenes de datos de diferente estructura.
Un servidor JDBC que hace fácil conectarnos con base de datos relacionales y permite procesar datos de igual manera que una herramienta BI tradicional.
En un ambiente Spark SQL, los 2 componentes más importantes son el DataFrame y el SQLContext. Que los veremos en próximos posts!!
Spark Sql nos permite consultar archivos batch, conjunto de datos Json o tablas Hive. Spark Sql trae características muy útiles y en las ultimas versiones ha agregado importantes mejoras en las que podemos nombrar:
DataFrames: es una abstracción que permite que funcione como SQL query engine distribuido.
Una Api de origen de datos (datasource) que permite conectarse con orígenes de datos de diferente estructura.
Un servidor JDBC que hace fácil conectarnos con base de datos relacionales y permite procesar datos de igual manera que una herramienta BI tradicional.
En un ambiente Spark SQL, los 2 componentes más importantes son el DataFrame y el SQLContext. Que los veremos en próximos posts!!
martes, 24 de abril de 2018
Eclipse Photon is coming...
Eclipse Photon, la decimoséptima versión anual del Proyecto Eclipse, se lanzará el 27 de junio de 2018, por lo visto trae varias mejoras. Entre las que podemos nombrar:
- Mejoras gráficas y mejor soporte para temas oscuros (que estan de moda)
- Mejor soporte a java 9 y 10. Por ejemplo, al crear un proyecto de Java 9 (o superior), ahora hay una opción para crear un archivo module-info.java.
- Todas las rutas de archivos (incluidos los duplicados) se muestran en el cuadro de diálogo Abrir recurso.
- Todos los archivos se actualizan automáticamente cuando se accede, sin intervención manual.
En fin muchos buenos cambios. Esperamos con ganas esta versión.
Dejo link: https://projects.eclipse.org/releases/photon
sábado, 21 de abril de 2018
Scala y swing se unen gracias scala-swing
Si queremos programar en Scala con ventanas podemos usar la plataforma Java. La plataforma Java nos ofrece diferentes opciones en las que tenemos a Swing.
Pero esto nos puede llevar mucho trabajo y tendríamos que llamar desde Scala funciones de java un lió, por ende Scala nos brinda una librería llamada scala-swing
scala-swing nos permite escribir código swing de forma Scala y a la vez nos facilita muchísimo este trabajo.
Veamos un ejemplo:
Programamos un archivo llamado: Ventana.scala
package com.assembly
import scala.swing._
import scala.swing.event._
object Ventana extends SimpleSwingApplication {
def top = new MainFrame {
title = "SwingApp"
var numclicks = 0
object label extends Label {
val prefix = "Tocaste el boton : "
text = prefix + "0 "
listenTo(button)
reactions += {
case ButtonClicked(button) =>
numclicks = numclicks + 1
text = prefix + numclicks
}
}
object button extends Button {
text = "Soy El buton"
}
contents = new FlowPanel {
contents.append(button, label)
border = Swing.EmptyBorder(5, 5, 5, 5)
}
}
}
Para llamar esta clase podemos utilizar un Objeto, llamado Main :
package com.assembly
object Main {
def main(args: Array[String]): Unit = {
val ventana = Ventana
ventana.startup(args)
}
}
Y Listo!!
Dejo link: https://github.com/scala/scala-swing
Pero esto nos puede llevar mucho trabajo y tendríamos que llamar desde Scala funciones de java un lió, por ende Scala nos brinda una librería llamada scala-swing
scala-swing nos permite escribir código swing de forma Scala y a la vez nos facilita muchísimo este trabajo.
Veamos un ejemplo:
Programamos un archivo llamado: Ventana.scala
package com.assembly
import scala.swing._
import scala.swing.event._
object Ventana extends SimpleSwingApplication {
def top = new MainFrame {
title = "SwingApp"
var numclicks = 0
object label extends Label {
val prefix = "Tocaste el boton : "
text = prefix + "0 "
listenTo(button)
reactions += {
case ButtonClicked(button) =>
numclicks = numclicks + 1
text = prefix + numclicks
}
}
object button extends Button {
text = "Soy El buton"
}
contents = new FlowPanel {
contents.append(button, label)
border = Swing.EmptyBorder(5, 5, 5, 5)
}
}
}
Para llamar esta clase podemos utilizar un Objeto, llamado Main :
package com.assembly
object Main {
def main(args: Array[String]): Unit = {
val ventana = Ventana
ventana.startup(args)
}
}
Y Listo!!
Dejo link: https://github.com/scala/scala-swing
martes, 17 de abril de 2018
Lenguajes que compilan para Python
Quiero compartir un link sobre un lenguajes que son compatibles con python o que pueden correr sobre la plataforma.
Lo interesante del link es la cantidad de lenguajes funcionales.
Y otra cosa interesante es que se puede bajar el libro: "Functional Programming in Python"
Dejo link:
https://github.com/vindarel/languages-that-compile-to-python
https://github.com/sfermigier/awesome-functional-python
domingo, 15 de abril de 2018
Ejemplo de una aplicación en Spark
La aplicación de muestra en esta sección es una aplicación simple para contar palabras. Este es el mismo ejemplo que se utiliza para enseñar el procesamiento de big data con Hadoop. Realizaremos algunos análisis de datos en un archivo de texto para contar cuántas palabras hay en el archivo y cuántas veces se repiten. El archivo de texto y el conjunto de datos en este ejemplo son pequeños, pero los mismos programas Spark se pueden usar para grandes conjuntos de datos sin modificaciones de código. De forma similar a Hadoop, el entorno de tiempo de ejecución Spark distribuirá automáticamente los datos a diferentes nodos en el clúster para un procesamiento de datos más rápido.
Para mantener el ejemplo simple, usaremos el shell Spark Scala.
Primero, instalemos Spark en nuestra máquina local, esto ya lo vimos en post pasados.
Con spark instalado y listo, podemos utilizar el API de stark para procesar archivos. Por lo tanto abrimos el shell de scala (yo voy a utilizar linux)
Me paro en la carpeta bin de spark y escribo:
$ ./spark-shell
Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
18/04/15 11:04:39 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
18/04/15 11:04:39 WARN Utils: Your hostname, toto resolves to a loopback address: 127.0.1.1; using 172.17.0.1 instead (on interface docker0)
18/04/15 11:04:39 WARN Utils: Set SPARK_LOCAL_IP if you need to bind to another address
Spark context Web UI available at http://172.17.0.1:4040
Spark context available as 'sc' (master = local[*], app id = local-1523801082307).
Spark session available as 'spark'.
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/___/ .__/\_,_/_/ /_/\_\ version 2.2.1
/_/
Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_161)
Type in expressions to have them evaluated.
Type :help for more information.
scala> import org.apache.spark.SparkContext
import org.apache.spark.SparkContext
scala> import org.apache.spark.SparkContext._
import org.apache.spark.SparkContext._
scala> val txtFile = "../NOTICE"
txtFile: String = ../NOTICE
scala> val txtData = sc.textFile(txtFile)
txtData: org.apache.spark.rdd.RDD[String] = ../NOTICE MapPartitionsRDD[1] at textFile at <console>:30
scala> txtData.cache()
res2: txtData.type = ../NOTICE MapPartitionsRDD[1] at textFile at <console>:30
scala> txtData.count()
res3: Long = 661
De esta manera sabemos la cantidad de lineas de archivo “NOTICE”, si queremos saber la cantidad de veces que aparece las palabras podemos hacer:
scala> val wcData = txtData.flatMap(l => l.split(" ")).map(word => (word, 1)).reduceByKey(_ + _)
wcData: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[6] at reduceByKey at <console>:36
scala> wcData.collect().foreach(println)
(created,1)
(Unless,4)
(Technology,1)
(Sébastien,1)
...
Lo que hace en la
primera linea es :
- Divide una linea por espacio “ ”
- Luego crea una tupla (palabra, 1), imaginate que queda algo así: (palabra1,1) , (palabra2,1), (palabra1,1), (palabra1,1)
- Por lo tanto aplica una reducción por key es decir va sumando cuantas veces aparecen las palabras agrupándolos por key y queda de la siguiente manera: (palabra1,3) , (palabra2,1)
En la segunda linea
imprimirme el resultado.
Y Listo!!
viernes, 13 de abril de 2018
Estadísticas de las base de datos relacionales.
Para que una base de datos relacional pueda resolver una consulta SQL de forma óptima necesita conocer los datos físicos de cada tabla, índice o cluster que intervienen en ella. Estos datos se almacenan en el diccionario de datos.
En oracle pueden ser consultadas usando las vistas adecuadas: dba_tables, dba_tab_statistics, dba_tab_col_statistics, dba_tab_histograms, dba_indexes, dba_ind_statistics… etc.
En concreto, es el optimizador quién de todos los planes de ejecución posibles analiza estos datos estadísticos para evaluar cuál de todos supone un menor coste en términos de I/O y uso de CPU.
Las estadísticas deben reflejar verazmente el estado físico de los objetos, y conforme vayan sufriendo transformaciones éstas se irán quedando obsoletas. Es por esto por lo que hay que recopilar las estadísticas de nuevo a medida que ya no reflejen la situación real de los objetos a los que describen.
Si una tabla no posee estadísticas, el motor de base de datos puede recopilar ciertos datos dinámicamente en el momento de la consulta. Esto se llama muestreo dinámico “dynamic sampling”.
Las estadísticas se pueden recopilar manual o automáticamente. Por omisión, Oracle recopila las estadísticas a través del job programado con scheduler en una ventana de tiempo predefinida: por ejemplo de lunes a viernes de 22:00 a 6:00 y sábados y domingos completos. Durante esta recopilación automática se toman datos de tablas sin estadísticas o con estadísticas obsoletas (que han sufrido más de 10% de modificaciones desde la anterior toma de datos) pero antes debe haberse configurado el parámetro STATISTICS_LEVEL a un valor distinto de BASIC.
En oracle para seguir el número de registros modificados existe la vista existe all_tab_modifications. Ésta muestra el número aproximado de inserciones, modificaciones, borrados y truncados que ha sufrido la tabla desde la última recopilación. La vista es consultable por el usuario pero hay que tener en cuenta que estos datos no son visibles inmediatamente. Existe un retardo de unos minutos para evitar que la escritura interfiera en el rendimiento.
Para recopilar las estadísticas manualmente hay diferentes funciones dependiendo el motor por ejemplo en oracle hay que usar el paquete DBMS_STATS. Dicho paquete tiene métodos para:
En Oracle podemos ejecutar las estadísticas para todos los esquemas de la siguiente forma:
SQL> exec dbms_stats.gather_database_stats;
Procedimiento PL/SQL terminado correctamente.
En Postgres por ejemplo existe una herramienta llamada ANALYZE que permite correr las estadísticas de forma manual :
ANALYZE [ VERBOSE ] [ table_name [ ( column_name [, ...] ) ] ]
Como se puede ver hay diferentes modos de correr esto pero lo más común sería:
ANALYZE VERBOSE users;
En sql server, tambien podemos actualizar las estadísticas utilizando UPDATE STATISTICS o el stored procedure sp_updatestats, veamos unos ejemplos:
USE AdventureWorks2012;
GO
UPDATE STATISTICS Sales.SalesOrderDetail;
GO
La actualización de estadísticas garantiza que las consultas compilan con estadísticas actualizadas. Sin embargo, actualizar las estadísticas hace que las consultas se recompilen. Por lo tanto puede haber una compensación de rendimiento entre la mejora de los planes de consulta y el tiempo que lleva recompilar las consultas.
Y por ultimo, algo muy importante es hacer backup tambien de las estadísticas, dado que si pasa algo con la base de datos, no solo vamos a querer restaurarla sino tambien que sea usable. Por lo tanto a la hora de hacer backup incluyamos las estadísticas.
En oracle pueden ser consultadas usando las vistas adecuadas: dba_tables, dba_tab_statistics, dba_tab_col_statistics, dba_tab_histograms, dba_indexes, dba_ind_statistics… etc.
En concreto, es el optimizador quién de todos los planes de ejecución posibles analiza estos datos estadísticos para evaluar cuál de todos supone un menor coste en términos de I/O y uso de CPU.
Las estadísticas deben reflejar verazmente el estado físico de los objetos, y conforme vayan sufriendo transformaciones éstas se irán quedando obsoletas. Es por esto por lo que hay que recopilar las estadísticas de nuevo a medida que ya no reflejen la situación real de los objetos a los que describen.
Si una tabla no posee estadísticas, el motor de base de datos puede recopilar ciertos datos dinámicamente en el momento de la consulta. Esto se llama muestreo dinámico “dynamic sampling”.
Las estadísticas se pueden recopilar manual o automáticamente. Por omisión, Oracle recopila las estadísticas a través del job programado con scheduler en una ventana de tiempo predefinida: por ejemplo de lunes a viernes de 22:00 a 6:00 y sábados y domingos completos. Durante esta recopilación automática se toman datos de tablas sin estadísticas o con estadísticas obsoletas (que han sufrido más de 10% de modificaciones desde la anterior toma de datos) pero antes debe haberse configurado el parámetro STATISTICS_LEVEL a un valor distinto de BASIC.
En oracle para seguir el número de registros modificados existe la vista existe all_tab_modifications. Ésta muestra el número aproximado de inserciones, modificaciones, borrados y truncados que ha sufrido la tabla desde la última recopilación. La vista es consultable por el usuario pero hay que tener en cuenta que estos datos no son visibles inmediatamente. Existe un retardo de unos minutos para evitar que la escritura interfiera en el rendimiento.
Para recopilar las estadísticas manualmente hay diferentes funciones dependiendo el motor por ejemplo en oracle hay que usar el paquete DBMS_STATS. Dicho paquete tiene métodos para:
- Recopilar estadísticas.
- Borrar estadísticas.
- Guardar y asignar estadísticas.
- Crear o borrar tablas donde guardar juegos de estadísticas.
- Bloquear y desbloquear las estadísticas de las tablas.
- Retornar las estadísticas que tenía una tabla en un momento dado.
En Oracle podemos ejecutar las estadísticas para todos los esquemas de la siguiente forma:
SQL> exec dbms_stats.gather_database_stats;
Procedimiento PL/SQL terminado correctamente.
En Postgres por ejemplo existe una herramienta llamada ANALYZE que permite correr las estadísticas de forma manual :
ANALYZE [ VERBOSE ] [ table_name [ ( column_name [, ...] ) ] ]
Como se puede ver hay diferentes modos de correr esto pero lo más común sería:
ANALYZE VERBOSE users;
En sql server, tambien podemos actualizar las estadísticas utilizando UPDATE STATISTICS o el stored procedure sp_updatestats, veamos unos ejemplos:
USE AdventureWorks2012;
GO
UPDATE STATISTICS Sales.SalesOrderDetail;
GO
La actualización de estadísticas garantiza que las consultas compilan con estadísticas actualizadas. Sin embargo, actualizar las estadísticas hace que las consultas se recompilen. Por lo tanto puede haber una compensación de rendimiento entre la mejora de los planes de consulta y el tiempo que lleva recompilar las consultas.
Y por ultimo, algo muy importante es hacer backup tambien de las estadísticas, dado que si pasa algo con la base de datos, no solo vamos a querer restaurarla sino tambien que sea usable. Por lo tanto a la hora de hacer backup incluyamos las estadísticas.
Suscribirse a:
Entradas (Atom)