39
Alasql.js база данных SQL на JavaScript Андрей Гершун [email protected] https://github.com/agershun/alasql MoscowJS 29 января 2015 года à la SQL 1

Alasql - база данных SQL на JavaScript (MoscowJS)

Embed Size (px)

Citation preview

1

Alasql.jsбаза данных SQL

на JavaScriptАндрей Гершун

[email protected]://github.com/agershun/alasql

MoscowJS29 января 2015 года

à laSQL

2

1. Что такое Alasql.js?2. Примеры использования Alasql3. Alasql изнутри4. Оптимизация

“Alasql - à la SQL parce que le monde entier envie notre belle langue”

Maxime Bertonnier, blogwebdev.fr

3

Ты помнишь, каквсе начиналось…

lodash v3.0.0_.sortByAll(collection, props)

4

Alasql.js – SQL на JavaScript?… Хм.

• Сложные SQL запросы и быстрая обработка данных на клиенте:

• WHERE• GROUP BY• HAVING• ORDER BY• JOIN• APPLY

• CSV, TAB, XLS, JSON

5

Применение

• Фронт-энд для Business Intelligence приложений

• OLAP• таблицы

• Client First • мобильные приложения с

неустойчивой связью с сервером

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

7

Подключение Alasql.js

Браузер

<script src=“alasql.js></script>

<script>

alasql(‘CREATE DATABASE test01’);

</script>

AMD или UMD

require([‘alasql’], function(alasql) {

alasql(‘SELECT * FROM courses’);

});

Node.js

npm install alasql

var alasql = require(‘alasql’);

8

Использование Alasql

Синхронный интерфейс:var res = alasql(sql, params);

Асинхронный интерфейс:alasql(sql, params, function(res, err) {

// res – результаты, err - ошибка});

9

Пример выполнения SQL-операторовalasql('CREATE DATABASE TEST01; \

USE TEST01; \

CREATE TABLE jedi ( \

jediid INT, \

name STRING \

); \

INSERT INTO jedi VALUES \

(100, “Анакин Скайуокер")'

);

Перевод на JavaScriptvar jedi = [];

jedi.pop({studentid: 100, name:‘Анакин Скайуокер'});

10

Пример SQL-запроса

var num = alasql('SELECT VALUE COUNT(*) FROM jedi');

Перевод на JavaScript

var num = jedi.length;

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)

12

Реализованная функциональность SQL• ROLLUP, CUBE, GROUPING

SETS• INNER LEFT RIGHT OUTER

SEMI ANTI NATURAL CROSS JOIN

• CROSS OUTER APPLY• Вложенные SELECT, EXISTS,

ANY, SOME

13

SQL и JavaScript – лучше вместе!var data = [

[1,2,3], [2,3,4], [5,6,7]

];var res = alasql('SELECT * FROM ? \

WHERE [0] < ?',[data, 2]);

Перевод на JavaScriptvar 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() … - непросто…

15

Сахар…

alasql(‘SELECT LEN(_) FROM “mytext.txt”’);

Результат: длины строк в файле mytext.txt

16

Работа с объектами и функциями JavaScript var data = [

{a:{b:[1,2,3,4]}, {a:{b:[2014,2015]}}

];

alasql(‘SELECT a->b->length FROM ?’,[data]);

Результат: [4,2]

17

Загрузка данных из файлов в браузере,

Загрузка данныхс сервера

Загрузка данныхс десктопа

Экспорт данныхна десктоп

Источники данных:• JSON• CSV, TAB• XLS, XLSX • Google Spreadsheets• HTML (тэг <table>)

18

19

20

Alasql для d3.js:Олимпийские медали из Excelalasql('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 - выборка медали по заданной оси

});

21

22

23

24

25

Пример: Подготовка данных для Google Maps из Slideshare.com

Данныепо

просмотрам

XLSX(на сервере)

Гео данныепо странам

CSV(в Интернете)

Данныепо

просмотрампо странамс указанием

широтыи долготы

МассивJavaScript

slideshare.com

github.com

GoogleMaps APIJOIN

26

SELECT countries.*, views.cntFROM (

SELECT Country, COUNT(*) AS cntFROM "all_latest_views_3m.csv"GROUP BY Country

) AS viewsJOIN (

SELECT *FROM "https://abc.com/lat-long-countries.csv

") AS countries USING Country

27

Alasql из консоли: Простой ETL

> node alacon “SELECT 2+2”4

> node alacon “SELECT * INTO 'medals.csv' FROM 'medals.xlsx' WHERE Year=2008”

28

SQL2: Alasql вместе с IndexedDB (а также Local Storage, File Storage, SQL.js)

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();

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>

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>

32

Alasql изнутри

1. Лексер и парсер• Jison

2. Интерпретатор• Интерпретация «больших» операторов

(CREATE DATABASE, CREATE TABLE и др.)

3. Компилятор• Компиляция «критичных по скорости»

операторов SELECT/INSERT/UPDATE/DELETE

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

34

http://jsperf.com/alasql-js-vs-websql/7

35

Оптимизация SQL• Анализ JOIN и WHERE выражений и преиндексация

FROM oneJOIN two USING eJOIN three ON two.a = three.a+1 AND two.b = three.c+three.dWHERE 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

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);

37

«Классическая» оптимизация JavaScript• for быстрее, чем forEach и т.д.•some быстрее, чем filter()•parseInt(x,10) быстрее, чем x|0

jsPerf.com - лучший советчик…

38

Тестирование

• Mocha.js• 240+ тестов для Node.js

и браузера• Нужно не менее 2000…

39

[email protected]@agershun

GitHub• https://github.com/agershun/alasql

Что дальше?