¿Qué es SQL? El primer lenguaje de analítica de datos

0
18

En la actualidad, Structured Query Language (SQL) es el medio estándar para manipular y consultar datos en bases de datos relacionales, aunque con extensiones privativas entre los productos. Incluso, la facilidad y la ubicuidad de SQL han llevado a los creadores de muchos almacenes de datos «NoSQL» o no relacionales, como Hadoop, a adoptar subconjuntos de SQL o crear sus propios lenguajes de consulta tipo SQL.

Pero SQL no siempre fue el lenguaje «universal» para las bases de datos relacionales. Desde el principio (alrededor de 1980), SQL tuvo ciertos strikes en su contra. Muchos investigadores y desarrolladores en ese momento, incluyéndome a mí, pensamos que la sobrecarga de SQL evitaría que fuese práctico en una base de datos de producción.

Claramente, estábamos equivocados. Pero muchos todavía creen que, a pesar de la facilidad y accesibilidad de SQL, el precio cobrado en el rendimiento del tiempo de ejecución es a menudo demasiado alto.

La historia de SQL
Antes de que SQL existiera, las bases de datos tenían interfaces de programación ajustadas y de navegación, y generalmente se diseñaban alrededor de un esquema de red llamado modelo de datos CODASYL. CODASYL (Committee on Data Systems Languages) fue un consorcio responsable del lenguaje de programación COBOL (a partir de 1959) y las extensiones de idiomas de bases de datos (a partir de 1969).

Cuando uno programaba contra una base de datos CODASYL, navegaba hacia registros a través de conjuntos, que expresan relaciones de-uno-a-muchos. Las bases de datos jerárquicas más antiguas solo permiten que un registro pertenezca a un conjunto. Las bases de datos de red permiten que un registro pertenezca a múltiples conjuntos.

Digamos que deseaba enumerar a los estudiantes inscritos en CS 101. Primero debía buscar «CS 101» en el conjunto de Courses por nombre, establecerlo como el propietario o padre del conjunto de Enrollees, encontrar el primer miembro (ffm) del conjunto de Enrollees, que es un registro de Student, y enumerarlo. Luego repetía el mismo ciclo: buscar el siguiente miembro (fnm) y enumerarlo. Cuando fnm fallaba, el ciclo vicioso paraba.

Puede parecer mucho trabajo pesado para el programador de la base de datos, pero fue muy eficiente en el tiempo de ejecución. Expertos como Michael Stonebraker de la Universidad de California en Berkeley e Ingres señalaron que hacer ese tipo de consulta en una base de datos CODASYL, como hizo IDMS, tomó aproximadamente la mitad del tiempo de CPU y menos de la mitad de la memoria que la misma consulta en una base de datos relacional usando SQL.

En comparación, la consulta SQL equivalente para devolver a todos los estudiantes en CS 101 sería algo como

SELECT student.name FROM courses, enrollees, students WHERE course.name =»CS 101″

Esa sintaxis implica una unión interna relacional (en realidad dos), como explicaré a continuación; y omite algunos detalles importantes, como los campos utilizados para las uniones.

Bases de datos relacionales y SQL
¿Por qué renunciaría a un factor de dos mejoras en la velocidad de ejecución y el uso de memoria? Había dos grandes razones: facilidad de desarrollo y portabilidad. No pensé que ninguno de los dos importara mucho en 1980 en comparación con los requisitos de rendimiento y memoria, pero a medida que el hardware de computadora mejoró y se volvió más barato, las personas dejaron de preocuparse por la velocidad de ejecución y la memoria, y se empezaron a preocupar por el costo del desarrollo.

En otras palabras, la Ley de Moore eliminó las bases de datos CODASYL en favor de las bases de datos relacionales. Como sucedió, la mejora en el tiempo de desarrollo fue significativa, pero la portabilidad de SQL resultó ser un sueño imposible.

¿De dónde provienen el modelo relacional y SQL? E.F. «Ted” Codd fue un científico de computación en el Laboratorio de Investigación de IBM San José que desarrolló la teoría del modelo relacional en la década de 1960 y la publicó en 1970. IBM tardó en implementar una base de datos relacional en un esfuerzo por proteger los ingresos de su base de datos CODASYL IMS/DB. Cuando IBM finalmente comenzó su proyecto System R, el equipo de desarrollo (Don Chamberlin y Ray Boyce) no estaba bajo las órdenes de Codd, e ignoraron el documento de lenguaje relacional Alfa de 1971 de Codd para diseñar su propio lenguaje, SEQUEL (Structured English Query Language). En 1979, antes de que IBM lanzara su producto, Larry Ellison incorporó el lenguaje en su base de datos Oracle (utilizando las publicaciones de SEQUEL previas al lanzamiento de IBM como su especificación). SEQUEL pronto se convirtió en SQL para evitar una violación de marca internacional.

Los «tom-toms beating for SQL” (como lo dijo Michael Stonebraker) venían no solo de Oracle e IBM, sino también de los clientes. No fue fácil contratar o capacitar a diseñadores y programadores de bases de datos CODASYL, por lo que SEQUEL (y SQL) parecían mucho más atractivos. SQL fue tan atractivo a fines de la década de 1980, que muchos proveedores de bases de datos esencialmente engraparon un procesador de consultas SQL sobre sus bases de datos CODASYL -para gran consternación de Codd, quien sentía que las bases de datos relacionales tenían que ser diseñadas desde cero para ser relacionales.

Una base de datos relacional pura, diseñada por Codd, está construida sobre tuplas agrupadas en relaciones, consistentes con la lógica de predicados de primer orden. Las bases de datos relacionales del mundo real tienen tablas que contienen campos, restricciones y disparadores, y las tablas están relacionadas a través de claves externas. SQL se utiliza para declarar los datos que serán devueltos, y un procesador de consultas SQL y un optimizador de consultas convierten la declaración SQL en un plan de consulta ejecutado por el motor de la base de datos.

SQL incluye un sub-idioma para definir esquemas, el lenguaje de definición de datos (DDL), junto con un sub-idioma para modificar datos, el lenguaje de manipulación de datos (DML). Ambos tienen raíces en las primeras especificaciones de CODASYL. El tercer sub-lenguaje en SQL declara consultas a través del enunciado SELECT y las uniones relacionales.

Enunciado SELECT de SQL
El enunciado SELECT le dice al optimizador de consultas qué datos devolver, en qué tablas buscar, qué relaciones seguir y qué orden imponerles a los datos devueltos. El optimizador de consultas tiene que averiguar por sí mismo qué índices usar para evitar escaneos de la tabla de fuerza bruta y lograr un buen rendimiento de la consulta, a menos que la base de datos particular admita sugerencias de índice.

Parte del arte del diseño de bases de datos relacionales depende del uso juicioso de los índices. Si omite un índice para una consulta frecuente, toda la base de datos puede ralentizarse con grandes cargas de lectura. Si cuenta con demasiados índices, toda la base de datos puede ralentizarse con cargas pesadas de escritura y actualización.

Otro arte importante es elegir una clave primaria adecuada y única para cada tabla. No solo se tiene que considerar el impacto de la clave primaria en las consultas comunes, sino también cómo se desempeñará en las uniones cuando aparezca como una clave externa en otra tabla, y cómo afectará la localidad de referencia de los datos.

En el caso avanzado de las tablas de bases de datos que se dividen en diferentes volúmenes según el valor de la clave primaria, llamada fragmentación horizontal, también se debe considerar cómo la clave primaria afectará la fragmentación. Sugerencia: debe buscar que la tabla se distribuya uniformemente entre los volúmenes, lo que sugiere que no desea utilizar sellos de fecha o números enteros consecutivos como claves primarias.

Las discusiones sobre el enunciado SELECT suelen comenzar de manera simple, pero pueden volverse confusas rápidamente. Considerar:

SELECT * FROM Customers;

Simple, ¿verdad? Solicita todos los campos y todas las filas de la tabla Customers. Supongamos, sin embargo, que la tabla Customers tiene cien millones de filas y cien campos, y uno de los campos es un campo de texto grande para comentarios. ¿Cuánto tiempo tardará extraer todos esos datos a través de una conexión de red de 10 megabits por segundo, si cada fila contiene un promedio de un kilobyte de datos?

Quizás se debería reducir la cantidad enviada por cable. Considerar:

SELECT TOP 100 companyName, lastSaleDate, lastSaleAmount, totalSalesAmount FROM Customers

WHERE state =»Ohio» AND city =»Cleveland»

ORDER BY lastSaleDate DESCENDING;

Ahora obtendrá muchos menos datos. Le ha pedido a la base de datos que le brinde solo cuatro campos, que solo considere las empresas en Cleveland y que le brinde solo las 100 empresas con las ventas más recientes. Sin embargo, para hacerlo de manera más eficiente en el servidor de la base de datos, la tabla Customers necesita un índice en state+city para la cláusula WHERE y un índice en lastSaleDate para las cláusulas ORDER BY y TOP 100.

Por cierto, TOP 100 es válido para SQL Server y SQL Azure, pero no para MySQL u Oracle. En MySQL, se usaría LIMIT 100 después de la cláusula WHERE. En Oracle, usaría un límite en ROWNUM como parte de la cláusula WHERE, es decir, WHERE … AND ROWNUM <= 100. Desafortunadamente, los estándares ANSI/ISO de SQL (y hay nueve de ellos hasta la fecha, que van desde 1986 hasta 2016) son limitados, y las bases de datos los sobrepasan e introducen sus propias cláusulas y características patentadas.

Uniones de SQL
Hasta ahora, describí la sintaxis SELECT para tablas individuales. Antes de que pueda explicar las cláusulas JOIN, usted debe comprender las claves externas y las relaciones entre tablas. Lo explicaré con ejemplos en DDL, usando la sintaxis de SQL Server.

La versión corta es bastante simple. Cada tabla que desee usar en las relaciones debe tener una restricción de clave primaria; esto puede ser un campo único o una combinación de campos definidos por una expresión. Por ejemplo:

CREATE TABLE Persons (
PersonID int NOT NULL PRIMARY KEY,
PersonName char(80),

Cada tabla que debe relacionarse con Persons debe tener un campo que corresponda a la clave primaria de Persons, y para preservar la integridad relacional ese campo debe tener una restricción de clave externa. Por ejemplo:

CREATE TABLE Orders (
OrderID int NOT NULL PRIMARY KEY,

PersonID int FOREIGN KEY REFERENCES Persons(PersonID)
);

Hay versiones más largas de ambos enunciados que usan la palabra clave CONSTRAINT, que le permite nombrar la restricción. Eso es lo que generan la mayoría de las herramientas de diseño de bases de datos.

Las claves primarias siempre están indexadas y son únicas (los valores de campo no se pueden duplicar). Otros campos pueden ser indexados opcionalmente. Suele ser útil crear índices para campos de clave externa y para campos que aparecen en las cláusulas WHERE y ORDER BY, aunque no siempre es el caso, debido a la sobrecarga potencial de las escrituras y actualizaciones.

¿Cómo escribiría una consulta que devuelva todos los pedidos realizados por «John Doe”?

SELECT PersonName, OrderID FROM Persons
INNER JOIN Orders ON Persons.PersonID = Orders.PersonID
WHERE PersonName =»John Doe»;

De hecho, hay cuatro tipos de JOIN: INNER, OUTER, LEFT, y RIGHT. INNER JOIN es el valor predeterminado (puede omitir la palabra INNER), y es el que incluye solo filas que contienen valores coincidentes en ambas tablas. Si desea enumerar a las personas, ya sea que tengan o no órdenes, debe usar LEFT JOIN, por ejemplo:

SELECT PersonName, OrderID FROM Persons
LEFT JOIN Orders ON Persons.PersonID = Orders.PersonID
ORDER BY PersonName;

Cuando comienza a realizar consultas que unen más de dos tablas, que usan expresiones o que fuerzan tipos de datos, la sintaxis puede volverse un poco complicada al principio. Afortunadamente, existen herramientas de desarrollo de bases de datos que pueden generar consultas SQL correctas para usted, usualmente arrastrando y soltando tablas y campos del diagrama de esquema en un diagrama de consulta.

Procedimientos almacenados de SQL
A veces, la naturaleza declarativa del enunciado SELECT no lo lleva a donde quiere ir. La mayoría de las bases de datos poseen una instalación llamada procedimientos almacenados. Desafortunadamente, esta es un área donde casi todas las bases de datos usan extensiones privativas de los estándares SQL ANSI/ISO.

En SQL Server, el dialecto inicial para los procedimientos almacenados (o procesos almacenados) era Transact-SQL, también conocido como T-SQL; en Oracle, era PL-SQL. Ambas bases de datos han agregado lenguajes adicionales para procedimientos almacenados, como C#, Java y R. Un procedimiento almacenado T-SQL simple podría ser solo una versión parametrizada de un enunciado SELECT. Sus ventajas son la facilidad de uso y la eficiencia. Los procedimientos almacenados se optimizan cuando se guardan, no cada vez que se ejecutan.

Un procedimiento almacenado T-SQL más complicado podría usar múltiples enunciados SQL, parámetros de entrada y salida, variables locales, bloques BEGIN…END, condiciones IF…THEN…ELSE, cursores (procesamiento fila por fila de un conjunto), expresiones, tablas temporales y una gran cantidad de otras sintaxis de procedimiento. Obviamente, si el lenguaje de procedimiento almacenado es C#, Java o R, deberá utilizar las funciones y la sintaxis de esos lenguajes de procedimiento. En otras palabras, a pesar del hecho de que la motivación para SQL era usar consultas declarativas estandarizadas, en el mundo real se ve mucha programación de servidores de procedimientos específicos de la base de datos.

Eso no nos lleva de vuelta a los viejos y malos tiempos de la programación de base de datos CODASYL (aunque los cursores se parecen), pero sí se aleja de las ideas que argumentan que las declaraciones SQL deben estandarizarse y que las preocupaciones de rendimiento deben dejarse para el optimizador de consultas de la base de datos. Al fin y al cabo, duplicar el rendimiento suele ser demasiado para dejarlo sobre la mesa.

Aprenda SQL
Los sitios enumerados a continuación pueden ayudarle a aprender SQL o descubrir las peculiaridades de varios dialectos SQL.

  • Codecademy. Aprenda SQL. Gratis e interactivo. Actualización Pro disponible por una tarifa.
  • Khan Academy. Introducción a SQL: Consultas y gestión de datos. Video tutorial gratis.
  • SoloLearn. Fundamentos de SQL. Orientado a MySQL. Gratis.
  • Problemas y soluciones de SQLEjercicios de SQL. Libro de texto interactivo y ejercicios. Gratis.
  • SQLZoo. Un tutorial interactivo de SQL desarrollado y mantenido por la Universidad Napier de Edimburgo. Admite Microsoft SQL Server, Oracle Database, MySQL, IBM DB2 y PostgreSQL. Gratis.
  • Tutorialspoint. Aprenda SQL. Solo texto, no interactivo. Gratis.
  • Udacity. Introducción a las bases de datos relacionales. Utiliza Python y requiere algunos conocimientos de Python. Gratis.
  • Udemy. Los cursos gratuitos incluyen Introducción a las bases de datos y consultas SQL, Base de datos MySQL para principiantes, Microsoft SQL para principiantes, SQL práctico para principiantes (SELECT, FROM, y WHERE), y Sachin Quickly Learns (SQL).
  • Vertabelo Academy. Conceptos básicos de SQL, Operación de datos en SQL, Creación de tablas en SQL y otros ocho cursos interactivos de SQL. Algunos cursos tienen pruebas gratuitas, pero luego puede haber una tarifa. Hay siete cursos adicionales para Microsoft SQL Server. El sitio también tiene una herramienta de diseño de base de datos gráfica para PostgreSQL, MySQL, Oracle Database, SQL Server, SQLite e IBM DB2.
  • W3Schools. Tutorial de SQL. Gratis y disponible sin registro.

Documentación de la base de datos

Referencia rápida de comandos SQL
DDL: CREATE, ALTER, DROP (tablas)
DMS: SELECT, INSERT, UPDATE, DELETE(filas)
DCL: GRANT, REVOKE(permisos)

Martin Heller, InfoWorld.com