"Доклад не про React", Антон Виноградов, MoscowJS 27
"Alasql.js — база данных SQL на JavaScript" — Андрей Гершун, MoscowJS 18
1. Alasql.js
база данных SQL
на JavaScript
Андрей Гершун
agershun@gmail.com
https://github.com/agershun/alasql
MoscowJS
29 января 2015 года
à la
SQL
1
2. 1. Что такое Alasql.js?
2. Примеры использования Alasql
3. Alasql изнутри
4. Оптимизация
“Alasql - à la SQL parce que le monde
entier envie notre belle langue”
Maxime Bertonnier, blogwebdev.fr
2
3. Ты помнишь, как
все начиналось…
lodash v3.0.0
_.sortByAll(collection, props)
3
4. Alasql.js – SQL на JavaScript?… Хм.
• Сложные SQL запросы и быстрая
обработка данных на клиенте:
• WHERE
• GROUP BY
• HAVING
• ORDER BY
• JOIN
• APPLY
• CSV, TAB, XLS, JSON
4
5. Применение
• Фронт-энд для Business
Intelligence приложений
• OLAP
• таблицы
• Client First
• мобильные приложения с
неустойчивой связью с сервером
5
6. Какие клиентские SQL базы данных
существуют для JavaScript?
• «Полноценные» SQL
• WebSQL (SQLite) – «вне стандарта» с 2011 года
• SQL.js (SQLite) – (1.5 Мб), Emscripten, небыстрый
• SequelSphere.js – закрытый код
• LINQ
• SQLike.js
• JSLinq.js и др.
• NoSQL
• IndexedDB
• Key-value хранилища
• PouchDB, ydn-db
• CrossFilter.js
6
9. Пример выполнения SQL-операторов
alasql('CREATE DATABASE TEST01;
USE TEST01;
CREATE TABLE jedi (
jediid INT,
name STRING
);
INSERT INTO jedi VALUES
(100, “Анакин Скайуокер")'
);
Перевод на JavaScript
var jedi = [];
jedi.pop({studentid: 100, name:‘Анакин Скайуокер'});
9
10. Пример SQL-запроса
var num = alasql('SELECT VALUE COUNT(*) FROM jedi');
Перевод на JavaScript
var num = jedi.length;
10
11. Реализованная функциональность SQL
• WITH SELECT TOP INTO FROM GROUP BY HAVING WHERE LIMIT FETCH
• SUM, COUNT, DISTINCT, MIN, MAX, FIRST, LAST
• ROLLUP(), CUBE(), GROUPING SETS()
• INNER LEFT RIGHT OUTER SEMI ANTI NATURAL CROSS JOIN
• UNION ALL EXCEPT INTERSECT
• CROSS OUTER APPLY
• Вложенные SELECT, EXISTS, ANY, SOME
• INSERT DELETE UPDATE
• CREATE DROP ATTACH USE DATABASE, SHOW DATABASES
• CREATE DROP TABLE, PRIMARY KEY, CREATE DROP VIEW
• IF ELSE WHILE BEGIN END
• DECLARE SET
• BEGIN COMMIT ROLLBACK TRANSACTION (ограничено)
• Стандартные функции, CAST/CONVERT
• a la LINQ (fluent interface)
11
12. Реализованная функциональность SQL
• ROLLUP, CUBE, GROUPING
SETS
• INNER LEFT RIGHT OUTER
SEMI ANTI NATURAL CROSS
JOIN
• CROSS OUTER APPLY
• Вложенные SELECT, EXISTS,
ANY, SOME
12
13. SQL и JavaScript – лучше вместе!
13
var data = [
[1,2,3],
[2,3,4],
[5,6,7]
];
var res = alasql('SELECT * FROM ?
WHERE [0] < ?',[data, 2]);
Перевод на JavaScript
var res = data.filter(function(d){return d[0] < 2});
14. Сколько строк нужно на JavaScript,
чтобы реализовать SQL запрос?
SELECT COUNT(*) FROM students
LEFT JOIN courses USING courseid
LEFT JOIN schools ON students.schoolid = schools.schoolid
WHERE courseid > 3
GROUP BY schools.schoolid, courses.courseid
ORDER BY courseid DESC, schoolid
Инструменты JavaScript:
• filter(), sort(), map(), reduce(), every(), some() … - непросто…
14
16. Работа с объектами и функциями JavaScript
var data = [
{a:{b:[1,2,3,4]},
{a:{b:[2014,2015]}}
];
alasql(‘SELECT a->b->length FROM ?’,[data]);
Результат: [4,2]
16
17. Загрузка данных из файлов в браузере,
Загрузка данных
с сервера
Загрузка данных
с десктопа
Экспорт данных
на десктоп
Источники данных:
• JSON
• CSV, TAB
• XLS, XLSX
• Google Spreadsheets
• HTML (тэг <table>)
17
20. Alasql для d3.js:
Олимпийские медали из Excel
20
alasql('SELECT '+axe+',
SUM([Gold Medals]) AS Gold,
SUM([Silver Medals]) AS Silver,
SUM([Bronze Medals]) AS Bronze
FROM "medals.csv"
GROUP BY '+axe+'
ORDER BY '+axe,[],function (data){
// data - выборка медали по заданной оси
});
25. Пример: Подготовка данных для Google
Maps из Slideshare.com
Данные
по
просмотрам
XLSX
(на сервере)
Гео данные
по странам
CSV
(в Интернете)
Данные
по
просмотрам
по странам
с указанием
широты
и долготы
Массив
JavaScript
slideshare.com
github.com
Google
Maps APIJOIN
25
26. SELECT countries.*, views.cnt
FROM (
SELECT Country, COUNT(*) AS cnt
FROM "all_latest_views_3m.csv"
GROUP BY Country
) AS views
JOIN (
SELECT *
FROM "https://abc.com/lat-long-countries.csv"
) AS countries USING Country
26
27. Alasql из консоли: Простой ETL
> node alacon “SELECT 2+2”
4
> node alacon “SELECT * INTO 'medals.csv'
FROM 'medals.xlsx' WHERE Year=2008”
27
28. SQL2: Alasql вместе с IndexedDB
(а также Local Storage, File Storage, SQL.js)
28
CREATE INDEXEDDB DATABASE IF NOT EXISTS geo;
ATTACH INDEXEDDB DATABASE geo;
USE geo;
DROP TABLE IF EXISTS cities;
CREATE TABLE cities;
SELECT * INTO cities FROM ?;
SELECT COLUMN *
FROM cities
WHERE population > 100000
ORDER BY city DESC
29. A la LINQ.
Текучий интерфейс ;)
var data = [{a:1,b:1},{a:2,b:-1},
{a:3,b:3},{a:1,b:5}];
var res = alasql(data).Top(2).GroupBy("a").exec();
29
30. Alasql в обычном режиме
<script src="alasql.min.js"></script>
<script>
var arr = [{a:1},{a:2},{a:1}];
alasql('CREATE TABLE one (a INT);
INSERT INTO one VALUES(10);
SELECT * INTO one FROM ?;
SELECT * FROM one',[arr], function(data){
// Выполняется в основном потоке
});
</script>
30
31. Alasql в Worker
<script src="alasql-worker.min.js"></script>
<script>
var arr = [{a:1},{a:2},{a:1}];
alasql('CREATE TABLE one (a INT);
INSERT INTO one VALUES(10);
SELECT * INTO one FROM ?;
SELECT * FROM one',[arr], function(data){
// Выполняется в основном потоке
});
</script>
31
32. Alasql изнутри
1. Лексер и парсер
• Jison
2. Интерпретатор
• Интерпретация «больших» операторов
(CREATE DATABASE, CREATE TABLE и др.)
3. Компилятор
• Компиляция «критичных по скорости»
операторов SELECT/INSERT/UPDATE/DELETE
32
33. Оптимизация запросов
SELECT SUM(test1.one), test1.two, test2.three
FROM test1
JOIN test2 ON test1.two = test2.two
WHERE test1.one > 5
GROUP BY test1.two, test2.three
ORDER BY three, sumone
33
35. Оптимизация SQL
• Анализ JOIN и WHERE выражений и преиндексация
FROM one
JOIN two USING e
JOIN three ON two.a = three.a+1 AND two.b = three.c+three.d
WHERE two.a > 10 AND three.c > 20
• Как сократить пробег?
• one.length x two.length x three.length
• Оптимизиация
• two.e - индекс (хэш) для demo.e
• (three.a+1) +’#’+ (three.c+three.d) – индекс для (two.a) +’#’+ (two.b)
• two.a > 10 – префильтрация массива one
• three.c > 20 – префильтрация массива two
35
36. Компиляция критических операций
(SELECT, WHERE, ORDER BY, GROUP BY, HAVING, INSERT, DELETE, UPDATE):
SELECT * FROM data ORDER BY alpha, beta
var orderfns = “
if(a.alpha>b.alpha) {return 1; else if(a.alpha==b.alpha) return 0;
if(a.beta>b.beta) {return 1; else if(a.beta==b.beta) return 0;
}}
return -1;”;
var orderfn = new Function(‘a,b’, orderfns);
var data = data.sort(orderfn);
36