SlideShare a Scribd company logo
1 of 220
Download to read offline
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
NoSQL? No, SQL!
How Modern SQL Databases
Come up with Algorithms
that You Would Have Never
Dreamed Of
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
NoSQL? No, SQL!
TL;DR:
SQL = Awesome
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Why are you here?
Because:
… This cannot be true
… This must not be true
… Is it true, though?
… OMG imma rewrite all code to SQL
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Me – @lukaseder
SQL is a device whose mystery
is only exceeded by its power!
- Founder and CEO at Data Geekery
- Oracle Java Champion
- JUG.ch Board Member
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
When you leave the room
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Why do I talk about SQL?
SQL is the only ever successful,
mainstream, and general-
purpose 4GL (Fourth-
Generation Programming
Language)
And it is awesome!
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Why doesn’t anyone else talk about SQL?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Why doesn’t anyone else talk about SQL?
¯_(シ)_/¯
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Why doesn’t anyone else talk about SQL?
Except Vlad
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Vlad shows JPA’s only important feature
His blog: http://tiny.cc/jpa-only-useful-feature
Vlad: Hibernate
Developer Advocate
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Vlad shows JPA’s only important feature
His blog: http://tiny.cc/jpa-only-useful-feature
Vlad: Hibernate
Developer Advocate
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What is SQL?
Who has seen
my other talk?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What is SQL?
I mean this one
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
10 SQL tricks to convince you SQL is awesome
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
10 SQL tricks to convince you SQL is awesome
Not that
hard to
find
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
A SQL trick
-- Query from http://explainextended.com/2013/12/31/happy-new-year-5/
WITH RECURSIVE q(r, i, rx, ix, g) AS (
SELECT r::DOUBLE PRECISION * 0.02, i::DOUBLE PRECISION * 0.02,
.0::DOUBLE PRECISION , .0::DOUBLE PRECISION, 0
FROM generate_series(-60, 20) r, generate_series(-50, 50) i
UNION ALL
SELECT r, i, CASE WHEN abs(rx * rx + ix * ix) <= 2 THEN rx * rx - ix * ix END + r,
CASE WHEN abs(rx * rx + ix * ix) <= 2 THEN 2 * rx * ix END + i, g + 1
FROM q
WHERE rx IS NOT NULL AND g < 99
)
SELECT array_to_string(array_agg(s ORDER BY r), '')
FROM (
SELECT i, r, substring(' .:-=+*#%@', max(g) / 10 + 1, 1) s
FROM q
GROUP BY i, r
) q
GROUP BY i
ORDER BY i
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
A SQL trick: Generating the Mandelbrot Set
-- Query from http://explainextended.com/2013/12/31/happy-new-year-5/
WITH RECURSIVE q(r, i, rx, ix, g) AS (
SELECT r::DOUBLE PRECISION * 0.02, i::DOUBLE PRECISION * 0.02,
.0::DOUBLE PRECISION , .0::DOUBLE PRECISION, 0
FROM generate_series(-60, 20) r, generate_series(-50, 50) i
UNION ALL
SELECT r, i, CASE WHEN abs(rx * rx + ix * ix) <= 2 THEN rx * rx - ix * ix END + r,
CASE WHEN abs(rx * rx + ix * ix) <= 2 THEN 2 * rx * ix END + i, g + 1
FROM q
WHERE rx IS NOT NULL AND g < 99
)
SELECT array_to_string(array_agg(s ORDER BY r), '')
FROM (
SELECT i, r, substring(' .:-=+*#%@', max(g) / 10 + 1, 1) s
FROM q
GROUP BY i, r
) q
GROUP BY i
ORDER BY i
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
But today…
But today, we’ll talk
about more basic SQL
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
But today…
But today, we’ll talk
about more basic SQL
(still awesome)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
But today…
Is this SQL?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Who can handle this SQL statement here?
SELECT *
FROM person
WHERE id = 42
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Easy stuff
Perfect
This talk is for you.
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What will I talk about?
• SQL is awesome
• SQL is productive
• SQL is fast
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What will I talk about?
• SQL is awesome
• SQL is productive
• SQL is fast
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
There are two ways of proving this
1. By example
2. By alternative (Java)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Disclaimer
This is going to be a high level,
conceptual story about SQL
We’re not going into deeper
levels.
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Business is asking
What is the daily
revenue of each
store
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Business is asking
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Business is asking
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Business is asking
What is the daily
revenue of each
store
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Business is asking
What is the daily
revenue of each
store
Film
Money
Day
JOIN
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
No problemo
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Easy, right?
SELECT
title, payment_date, SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, payment_date
ORDER BY title, payment_date
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Easy, right?
SELECT
title, payment_date, SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, payment_date
ORDER BY title, payment_date
Money per film
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Easy, right?
SELECT
title, payment_date, SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, payment_date
ORDER BY title, payment_date
Relationship film ↔ money
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Easy, right?
SELECT
title, payment_date, SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, payment_date
ORDER BY title, payment_date
Aggregation per film / date
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Imperative style
Let’s write this in
«classic» Java
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
“Classic Java”
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s get rolling
class Film {
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s get rolling
You still with me?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Obviously, Film is a tuple
class Film {
int filmId;
String title;
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Because, Java
class Film {
int filmId;
String title;
int getFilmId() {
return filmId;
}
...
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Never forget these, of course
class Film {
int filmId;
String title;
int getFilmId() { ... }
void setFilmId(int filmId) { ... }
String getTitle() { ... }
void setTitle(String title) { ... }
int hashCode() { ... }
boolean equals(Object o) { ... }
String toString() { ... }
...
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Abstractions, ladies and gentlemen!
class FilmFactory {
Film newFilm() { ... }
}
class FilmFactoryBuilder {
FilmFactory newFilmFactory() { ... }
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Abstractions, ladies and gentlemen!
interface FilmFactory {
Film newFilm();
}
interface FilmFactoryBuilder {
FilmFactory newFilmFactory();
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Just to be sure, super generic!
interface FilmFactory {
Film newFilm();
}
interface FilmFactoryBuilder {
FilmFactory newFilmFactory();
}
class FilmFactoryImpl {
@Override
public Film newFilm() { ... }
}
class FilmFactoryBuilderImpl {
@Override
public FilmFactory newFilmFactory() { ... }
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Some Spring
interface FilmFactory {
Film newFilm();
}
interface FilmFactoryBuilder {
FilmFactory newFilmFactory();
}
@Bean
class FilmFactoryImpl {
@Override
public Film newFilm() { ... }
}
@Bean
class FilmFactoryBuilderImpl {
@Override
@EnableCaching
public FilmFactory newFilmFactory() { ... }
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Some Spring, and a little Lombok
@FunctionalInterface
interface FilmFactory {
Film newFilm();
}
@FunctionalInterface
interface FilmFactoryBuilder {
FilmFactory newFilmFactory();
}
@Bean
@EnableAspectJAutoProxy
@EnableAutoConfiguration
class FilmFactoryImpl {
@Override
public Film newFilm() { ... }
}
@Bean
@Configuration
@NoArgsConstructor
class FilmFactoryBuilderImpl {
@Override
@EnableCaching
public FilmFactory newFilmFactory() { ... }
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Oh, what the heck
@FunctionalInterface
interface FilmFactory {
Film newFilm();
}
@FunctionalInterface
interface FilmFactoryBuilder {
FilmFactory newFilmFactory();
}
@Bean
@EnableAspectJAutoProxy
@EnableAutoConfiguration
class FilmFactoryImpl {
@Override
public Film newFilm() { ... }
}
@Bean
@Configuration
@NoArgsConstructor @Cloneable @SneakyThrows
@ResultSetMapping @ConcurrentInitialiserProxyFactory
@SpringPrefetchAdapter @AdapterProxyBeanMethod @AdapterBeanProxyMethod
class FilmFactoryBuilderImpl {
@Override
@EnableCaching
public FilmFactory newFilmFactory() { ... }
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Oh, what the heck
@FunctionalInterface
interface FilmFactory {
Film newFilm();
}
@FunctionalInterface
interface FilmFactoryBuilder {
FilmFactory newFilmFactory();
}
@Bean
@EnableAspectJAutoProxy
@EnableAutoConfiguration
class FilmFactoryImpl {
@Override
@ThisMethodDidntHaveAnnotationsYet @OKWeStillHaveSomeSpaceLeft @LetsSeeIfWeCanReachThePrintMargin
public Film newFilm() { ... }
}
@Bean
@Configuration
@NoArgsConstructor @Cloneable @SneakyThrows
@ResultSetMapping @ConcurrentInitialiserProxyFactory
@SpringPrefetchAdapter @AdapterProxyBeanMethod @AdapterBeanProxyMethod
@MoreAndMoreAnnotations @CanYouEvenReadThis
@IsThereStillAnyRealLogicLeft
@ThisJokeNeverGetsLame @Annotatiomania @WhoWillBeNextYearsAnnotatiomaniac
class FilmFactoryBuilderImpl {
@Override
@EnableCaching
public FilmFactory newFilmFactory() { ... }
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Average enterprise bean is visible from space
@FunctionalInterface
interface FilmFactory {
Film newFilm();
}
@FunctionalInterface @NoArgsConstructor @Cloneable @SneakyThrows
interface FilmFactoryBuilder {
FilmFactory newFilmFactory();
}
@Bean
@EnableAspectJAutoProxy @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows
@EnableAutoConfiguration @NoArgsConstructor @Cloneable @SneakyThrows
class FilmFactoryImpl {
@Override @NoArgsConstructor @Cloneable @SneakyThrows
@ThisMethodDidntHaveAnnotationsYet @OKWeStillHaveSomeSpaceLeft @LetsSeeIfWeCanReachThePrintMargin
public Film newFilm() { ... }
}
@Bean
@Configuration @NoArgsConstructor @Cloneable @SneakyThrows
@NoArgsConstructor @Cloneable @SneakyThrows
@ResultSetMapping @ConcurrentInitialiserProxyFactory
@SpringPrefetchAdapter @AdapterProxyBeanMethod @AdapterBeanProxyMethod @NoArgsConstructor @Cloneable @SneakyThrows
@MoreAndMoreAnnotations @CanYouEvenReadThis @NoArgsConstructor @Cloneable @SneakyThrows
@IsThereStillAnyRealLogicLeft @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable
@SneakyThrows
@ThisJokeNeverGetsLame @Annotatiomania @WhoWillBeNextYearsAnnotatiomaniac
class FilmFactoryBuilderImpl {
@Override
@EnableCaching
public FilmFactory newFilmFactory() { ... }
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Enough of this. More info here
www.annotatiomania.com
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Hmm, relationships?
class Film {
int filmId;
String title;
int getFilmId() { ... }
void setFilmId(int filmId) { ... }
String getTitle() { ... }
void setTitle(String title) { ... }
// Hmm... Inventory? Store? Rental? Payment?
int hashCode() { ... }
boolean equals(Object o) { ... }
String toString() { ... }
...
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s assume, we copy relational model 1:1
class Film {
int filmId;
String title;
int getFilmId() { ... }
void setFilmId(int filmId) { ... }
String getTitle() { ... }
void setTitle(String title) { ... }
List<Inventory> getInventories() { ... }
int hashCode() { ... }
boolean equals(Object o) { ... }
String toString() { ... }
...
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s assume, we copy relational model 1:1
class Film {
int filmId;
String title;
int getFilmId() { ... }
void setFilmId(int filmId) { ... }
String getTitle() { ... }
void setTitle(String title) { ... }
@OneToMany(mappedBy = "film")
List<Inventory> getInventories() { ... }
int hashCode() { ... }
boolean equals(Object o) { ... }
String toString() { ... }
...
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s assume, we copy relational model 1:1
class Film {
int filmId;
String title;
int getFilmId() { ... }
void setFilmId(int filmId) { ... }
String getTitle() { ... }
void setTitle(String title) { ... }
@OneToMany(mappedBy = "film")
List<Inventory> getInventories() { ... }
int hashCode() { ... }
boolean equals(Object o) { ... }
String toString() { ... }
...
}
Anyone seen these lovely things?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s assume, we copy relational model 1:1
class Film {
int filmId;
String title;
int getFilmId() { ... }
void setFilmId(int filmId) { ... }
String getTitle() { ... }
void setTitle(String title) { ... }
@OneToMany(mappedBy = "film", fetch = FetchType.EAGER)
List<Inventory> getInventories() { ... }
int hashCode() { ... }
boolean equals(Object o) { ... }
String toString() { ... }
...
}
How about this? Care discuss this?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s assume, we copy relational model 1:1
class Film {
int filmId;
String title;
int getFilmId() { ... }
void setFilmId(int filmId) { ... }
String getTitle() { ... }
void setTitle(String title) { ... }
@OneToMany(mappedBy = "film", fetch = FetchType.LAZY)
List<Inventory> getInventories() { ... }
int hashCode() { ... }
boolean equals(Object o) { ... }
String toString() { ... }
...
}
How about this? Care discuss this?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
If you must @OneToMany
Ask Vlad
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Now, calculate. This be the result type
// This is the optimal result type
Map<Film,
Map<LocalDate, BigDecimal>>
result = new HashMap<>();
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Now, calculate. This be the result type
// This is the optimal result type
Map<Film,
Map<LocalDate, BigDecimal>>
result = new HashMap<>();
Money
Per film
Per date
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Money, eh?
JSR 354 FTW!
(Java Money API)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Money, eh?
JSR 354 FTW!
(Java Money API)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Now, calculate. This be the result type
// This is the optimal result type
Map<Film,
Map<LocalDate, BigDecimal>>
result = new HashMap<>();
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Now, calculate. Wait…
// Or this?
Map<Film,
Map<LocalDate, BigDecimal>>
result = new LinkedHashMap<>();
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Now, calculate. Or better
// Or maybe this?
SortedMap<Film,
SortedMap<LocalDate, BigDecimal>>
result = new TreeMap<>();
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Now, calculate. Aagh
// Kewl, wrote some library
MultiKeyMap<
Film, LocalDate, BigDecimal>
result = new MultiKeyMap<>();
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Five hours later
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Who in here has felt this way before?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Now let’s calculate, for real
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Easy, so far
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Easy, so far
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
// FIXME 2002-04-01 Will optimize this later
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Easy, so far
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
// FIXME 2003-04-01 Will optimize this “later”
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Easy, so far
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
// FIXME 2003-04-01 Will optimize this “later”
// FIXME 2005-04-01 URGENT! This is really slow!
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Still following?
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films)
; // TODO
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Still following?
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
// TODO
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Still following?
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
// TODO
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Aaah, lazy initialization!
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) {
daily = new HashMap<>();
result.put(film, daily);
}
// TODO
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Aaah, lazy initialization!
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) {
daily = new HashMap<>();
result.put(film, daily);
}
// TODO
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s have that Map discussion again
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) {
daily = new LinkedHashMap<>(); // TODO: Better Map!
result.put(film, daily);
}
// TODO
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
OK, next
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) { ... }
// TODO
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
OK, now looping
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) { ... }
for (Inventory inventory : film.getInventories())
; // TODO
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
OK, now looping
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) { ... }
for (Inventory inventory : film.getInventories())
for (Rental rental : inventory.getRentals())
; // TODO
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
OK, now looping
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) { ... }
for (Inventory inventory : film.getInventories())
for (Rental rental : inventory.getRentals())
for (Payment payment : rental.getPayments())
; // TODO
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
OK, now looping
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) { ... }
for (Inventory inventory : film.getInventories())
for (Rental rental : inventory.getRentals())
for (Payment payment : rental.getPayments())
; // TODO
}
EAGER or LAZY?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
OK, now looping
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) { ... }
for (Inventory inventory : film.getInventories())
for (Rental rental : inventory.getRentals())
for (Payment payment : rental.getPayments())
; // TODO
}
Or, entity graph?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Entity Graph – How JPA folks write SQL
@NamedEntityGraph(
name = "graph.film.inventories.rentals.payments",
attributeNodes = @NamedAttributeNode(
value = "inventories",
subgraph = "inventories"
),
subgraphs = {
@NamedSubgraph(
name = "inventories",
attributeNodes = @NamedAttributeNode(
value = "rentals",
subgraph = "rentals"
)
), ...
}
)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Entity Graph – How JPA folks write SQL
@NamedEntityGraph(
name = "graph.film.inventories.rentals.payments",
attributeNodes = @NamedAttributeNode(
value = "inventories",
subgraph = "inventories"
),
subgraphs = {
@NamedSubgraph(
name = "inventories",
attributeNodes = @NamedAttributeNode(
value = "rentals",
subgraph = "rentals"
)
), ...
}
)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Remember this slide?
@FunctionalInterface
interface FilmFactory {
Film newFilm();
}
@FunctionalInterface @NoArgsConstructor @Cloneable @SneakyThrows
interface FilmFactoryBuilder {
FilmFactory newFilmFactory();
}
@Bean
@EnableAspectJAutoProxy @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows
@EnableAutoConfiguration @NoArgsConstructor @Cloneable @SneakyThrows
class FilmFactoryImpl {
@Override @NoArgsConstructor @Cloneable @SneakyThrows
@ThisMethodDidntHaveAnnotationsYet @OKWeStillHaveSomeSpaceLeft @LetsSeeIfWeCanReachThePrintMargin
public Film newFilm() { ... }
}
@Bean
@Configuration @NoArgsConstructor @Cloneable @SneakyThrows
@NoArgsConstructor @Cloneable @SneakyThrows
@ResultSetMapping @ConcurrentInitialiserProxyFactory
@SpringPrefetchAdapter @AdapterProxyBeanMethod @AdapterBeanProxyMethod @NoArgsConstructor @Cloneable @SneakyThrows
@MoreAndMoreAnnotations @CanYouEvenReadThis @NoArgsConstructor @Cloneable @SneakyThrows
@IsThereStillAnyRealLogicLeft @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable
@SneakyThrows
@ThisJokeNeverGetsLame @Annotatiomania @WhoWillBeNextYearsAnnotatiomaniac
class FilmFactoryBuilderImpl {
@Override
@EnableCaching
public FilmFactory newFilmFactory() { ... }
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Your code now visible from Andromeda Galaxy
@FunctionalInterface
interface FilmFactory {
Film newFilm();
}
@FunctionalInterface @NoArgsConstructor @Cloneable @SneakyThrows
interface FilmFactoryBuilder {
FilmFactory newFilmFactory();
}
@Bean
@EnableAspectJAutoProxy @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows
@EnableAutoConfiguration @NoArgsConstructor @Cloneable @SneakyThrows
class FilmFactoryImpl {
@Override @NoArgsConstructor @Cloneable @SneakyThrows
@ThisMethodDidntHaveAnnotationsYet @OKWeStillHaveSomeSpaceLeft @LetsSeeIfWeCanReachThePrintMargin
public Film newFilm() { ... }
}
@Bean
@Configuration @NoArgsConstructor @Cloneable @SneakyThrows
@NoArgsConstructor @Cloneable @SneakyThrows
@ResultSetMapping @ConcurrentInitialiserProxyFactory
@SpringPrefetchAdapter @AdapterProxyBeanMethod @AdapterBeanProxyMethod @NoArgsConstructor @Cloneable @SneakyThrows
@MoreAndMoreAnnotations @CanYouEvenReadThis @NoArgsConstructor @Cloneable @SneakyThrows
@IsThereStillAnyRealLogicLeft @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable
@SneakyThrows
@ThisJokeNeverGetsLame @Annotatiomania @WhoWillBeNextYearsAnnotatiomaniac
class FilmFactoryBuilderImpl {
@Override
@EnableCaching
public FilmFactory newFilmFactory() { ... }
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
OK, now looping, done. Right?
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) { ... }
for (Inventory inventory : film.getInventories())
for (Rental rental : inventory.getRentals())
for (Payment payment : rental.getPayments())
daily.put(
payment.getPaymentDate(),
payment.getAmount());
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
OK, now looping, done. Wrong!
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily = result.get(film);
if (daily == null) { ... }
for (Inventory inventory : film.getInventories())
for (Rental rental : inventory.getRentals())
for (Payment payment : rental.getPayments()) {
LocalDate date = payment.getPaymentDate();
BigDecimal amount = payment.getAmount();
if (daily.containsKey(date))
daily.put(date, daily.get(date).add(amount));
else
daily.put(date, amount);
}
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
OK, now looping, done. OK, better with Java 8
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily =
result.computeIfAbsent(film, k -> new HashMap<>());
for (Inventory inventory : film.getInventories())
for (Rental rental : inventory.getRentals())
for (Payment payment : rental.getPayments())
daily.compute(
payment.getPaymentDate(),
(k, v) -> v == null
? payment.getAmount()
: payment.getAmount().add(v));
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Feel good about yourself?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Business is asking again
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Programmer reactions
SQL Developer Java Developer
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
SQL dev: I knew this was coming!
SELECT
title, payment_date, SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, payment_date
ORDER BY title, payment_date
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
SQL dev: Swoosh!
SELECT
title, payment_date, SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, payment_date
ORDER BY title, payment_date
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
SQL dev: Joke’s on you!
SELECT
title, store_id, payment_date, SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, store_id, payment_date
ORDER BY title, store_id, payment_date
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Java dev: Gaaah, OK
Map<Film, Map<LocalDate, BigDecimal>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily =
result.computeIfAbsent(film, k -> new HashMap<>());
for (Inventory inventory : film.getInventories())
for (Rental rental : inventory.getRentals())
for (Payment p : rental.getPayments())
daily.compute(
p.getPaymentDate(),
(k, v) -> v == null ? p.getAmount() : p.getAmount().add(v));
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Java dev: Let’s make some room
Map<Film, Map<LocalDate, BigDecimal> > result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<LocalDate, BigDecimal> daily =
result.computeIfAbsent(film, k -> new HashMap<>());
for (Inventory inventory : film.getInventories())
for (Rental rental : inventory.getRentals())
for (Payment p : rental.getPayments())
daily.compute(
p.getPaymentDate(),
(k, v) -> v == null ? p.getAmount() : p.getAmount().add(v));
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Java dev: Let’s see, if I tweak this and then…
Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore =
result.computeIfAbsent(film, k -> new HashMap<>());
for (Inventory inventory : film.getInventories()) {
Map<LocalDate, BigDecimal> daily =
dailyPerStore.computeIfAbsent(
inventory.getStoreId(), k -> new HashMap());
for (Rental rental : inventory.getRentals())
for (Payment p : rental.getPayments())
daily.compute(
p.getPaymentDate(),
(k, v) -> v == null ? p.getAmount() : p.getAmount().add(v));
}
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Java dev: Let’s see, if I tweak this and then…
Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore =
result.computeIfAbsent(film, k -> new HashMap<>());
for (Inventory inventory : film.getInventories()) {
Map<LocalDate, BigDecimal> daily =
dailyPerStore.computeIfAbsent(
inventory.getStoreId(), k -> new HashMap());
for (Rental rental : inventory.getRentals())
for (Payment p : rental.getPayments())
daily.compute(
p.getPaymentDate(),
(k, v) -> v == null ? p.getAmount() : p.getAmount().add(v));
}
}Architect:
(that’s this guy)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Java dev: Let’s see, if I tweak this and then…
Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore =
result.computeIfAbsent(film, k -> new HashMap<>());
for (Inventory inventory : film.getInventories()) {
Map<LocalDate, BigDecimal> daily =
dailyPerStore.computeIfAbsent(
inventory.getStoreId(), k -> new HashMap());
for (Rental rental : inventory.getRentals())
for (Payment p : rental.getPayments())
daily.compute(
p.getPaymentDate(),
(k, v) -> v == null ? p.getAmount() : p.getAmount().add(v));
}
}Architect: We can’t have such types.
Factor out in a new class. And Factory
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore =
result.computeIfAbsent(film, k -> new HashMap<>());
for (Inventory inventory : film.getInventories()) {
Map<LocalDate, BigDecimal> daily =
dailyPerStore.computeIfAbsent(
inventory.getStoreId(), k -> new HashMap());
for (Rental rental : inventory.getRentals())
for (Payment p : rental.getPayments())
daily.compute(
p.getPaymentDate(),
(k, v) -> v == null ? p.getAmount() : p.getAmount().add(v));
}
}
And you’re like…
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Meanwhile…
While you and your
architect engage in
nominal vs structural
typing philosophies...
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Meanwhile… The inevitable
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What on earth is a cumulative sum??
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What on earth is a cumulative sum??
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What on earth is a cumulative sum??
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Java dev: 😵
// Thanks God it’s Friday!
throw new UnsupportedOperationException();
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Meanwhile, the SQL developer…
SELECT
title, store_id, payment_date,
SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, store_id, payment_date
ORDER BY title, store_id, payment_date
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Meanwhile, the SQL developer…
SELECT
title, store_id, payment_date,
SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, store_id, payment_date
ORDER BY title, store_id, payment_date
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Meanwhile, the SQL developer…
SELECT
title, store_id, payment_date,
SUM(SUM(amount)) OVER (
PARTITION BY title, store_id
ORDER BY payment_date
)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, store_id, payment_date
ORDER BY title, store_id, payment_dateWindow function
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What does it do?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
3GL vs. 4GL
Do you
get the
message?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
3GL vs. 4GL
SQL is a 4GL
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
3GL vs. 4GL
In SQL, we only
declare the result.
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
3GL vs. 4GL
The database will
figure out the
algorithm for us.
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
3GL vs. 4GL
Algorithms are
boring (mostly)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
3GL vs. 4GL
We don’t care about
• Writing algorithms (using them is a different story)
• Premature Optimisation
• Data type details (HashMap<A, B> or List<Entry<A, B>>?)
• Local variables
• Caches
• Loops
• Initialisation (or NullPointerException)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
3GL vs. 4GL
We do care about
• Business logic
• Just a bit of indexing
That’s it!
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Is Java 8 Streams “declarative” ?
The Stream API
looks a lot like
SQL’s declarative
style
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Is Java 8 Streams “declarative” ?
The Stream API
looks a lot like
SQL’s declarative
style
FROM
WHERE
FETCH NEXT
GROUP BY
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
In a way, it’s very similar
TABLE : Stream<Tuple<..>>
SELECT : map()
DISTINCT : distinct()
JOIN : flatMap()
WHERE / HAVING : filter()
GROUP BY : collect()
ORDER BY : sorted()
UNION ALL : concat()
See:
http://blog.jooq.org/2015/08/13/common-sql-clauses-and-their-equivalents-in-java-8-streams/
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...;
List<Film> films = loadAllFilms(); // TODO
for (Film film : films) {
Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore =
result.computeIfAbsent(film, k -> new HashMap<>());
for (Inventory inventory : film.getInventories()) {
Map<LocalDate, BigDecimal> daily =
dailyPerStore.computeIfAbsent(
inventory.getStoreId(), k -> new HashMap());
for (Rental rental : inventory.getRentals())
for (Payment p : rental.getPayments())
daily.compute(
p.getPaymentDate(),
(k, v) -> v == null ? p.getAmount() : p.getAmount().add(v));
}
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms()
.stream()
.flatMap(f -> f.getInventories().stream())
.flatMap(i -> i.getRentals().stream())
.flatMap(r -> r.getPayments().stream())
.collect(... /* amount per film and store */ ...);
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms()
.stream() // Stream<Film>
.flatMap(f -> f.getInventories().stream()) // Stream<Inventory>
.flatMap(i -> i.getRentals().stream()) // Stream<Rental>
.flatMap(r -> r.getPayments().stream()) // Stream<Payment>
.collect(... /* amount per film and store */ ...);
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms()
.stream() // Stream<Film>
.flatMap(f -> f.getInventories().stream()) // Stream<Inventory>
.flatMap(i -> i.getRentals().stream()) // Stream<Rental>
.flatMap(r -> r.getPayments().stream()) // Stream<Payment>
.collect(... /* amount per film and store */ ...);
How to access «f» and «i» in
the Collector?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms()
.stream()
.flatMap(f -> f.getInventories().stream().map(i -> entry(f, i)))
.flatMap(fi -> fi.v2.getRentals().stream().map(r -> entry(fi, r)))
.flatMap(fir -> fir.v3.getPayments().stream().map(p -> entry(fir, p)))
.collect(... /* amount per film and store */ ...);
Use some wrapper types and pray
for stack allocation to happen
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms()
.stream()
.flatMap(f -> f.getInventories().stream().map(i -> entry(f, i)))
.flatMap(fi -> fi.v2.getRentals().stream().map(r -> entry(fi, r)))
.flatMap(fir -> fir.v3.getPayments().stream().map(p -> entry(fir, p)))
.collect(
Collectors.groupingBy(firp -> firp.getKey().getKey().getKey(),
Collectors.groupingBy(firp -> firp.getKey().getKey().getValue()
.getStoreId(),
Collectors.groupingBy(firp -> firp.getValue().getPaymentDate(),
Collectors.summingDouble(
firp -> firp.getValue().getAmount().doubleValue()
)
)
)
)
);
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms()
.stream()
.flatMap(f -> f.getInventories().stream().map(i -> entry(f, i)))
.flatMap(fi -> fi.v2.getRentals().stream().map(r -> entry(fi, r)))
.flatMap(fir -> fir.v3.getPayments().stream().map(p -> entry(fir, p)))
.collect(
Collectors.groupingBy(firp -> firp.getKey().getKey().getKey(),
Collectors.groupingBy(firp -> firp.getKey().getKey().getValue()
.getStoreId(),
Collectors.groupingBy(firp -> firp.getValue().getPaymentDate(),
Collectors.summingDouble(
firp -> firp.getValue().getAmount().doubleValue()
)
)
)
)
);
But what the hell is this?
(╯°□°)╯︵ ┻━┻
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Well, it certainly
looks declarative
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
We can do a bit better, though
Better Streams:
https://github.com/jOOQ/jOOL
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
We can do a bit better, though
Seq.seq(persons)
.collect(
count(),
max(Person::getAge),
min(Person::getHeight),
avg(Person::getWeight)
);
// (3, Optional[35],
// Optional[1.69], Optional[70.0])
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms()
.stream()
.flatMap(f -> f.getInventories().stream().map(i -> entry(f, i)))
.flatMap(fi -> fi.v2.getRentals().stream().map(r -> entry(fi, r)))
.flatMap(fir -> fir.v3.getPayments().stream().map(p -> entry(fir, p)))
.collect(
Collectors.groupingBy(firp -> firp.getKey().getKey().getKey(),
Collectors.groupingBy(firp -> firp.getKey().getKey().getValue()
.getStoreId(),
Collectors.groupingBy(firp -> firp.getValue().getPaymentDate(),
Collectors.summingDouble(
firp -> firp.getValue().getAmount().doubleValue()
)
)
)
)
);
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result =
Seq.seq(loadAllFilms())
.flatMap(f -> f.getInventories().stream().map(i -> entry(f, i)))
.flatMap(fi -> fi.v2.getRentals().stream().map(r -> entry(fi, r)))
.flatMap(fir -> fir.v3.getPayments().stream().map(p -> entry(fir, p)))
.collect(
Collectors.groupingBy(firp -> firp.getKey().getKey().getKey(),
Collectors.groupingBy(firp -> firp.getKey().getKey().getValue()
.getStoreId(),
Collectors.groupingBy(firp -> firp.getValue().getPaymentDate(),
Collectors.summingDouble(
firp -> firp.getValue().getAmount().doubleValue()
)
)
)
)
);
Use a Seq instead of a Stream
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result =
Seq.seq(loadAllFilms())
.crossApply(f -> f.getInventories())
.crossApply(fi -> fi.v2.getRentals())
.crossApply(fir -> fir.v2.getPayments())
.collect(
Collectors.groupingBy(firp -> firp.v1.v1.v1,
Collectors.groupingBy(firp -> firp.v1.v1.v2.getStoreId(),
Collectors.groupingBy(firp -> firp.v2.getPaymentDate(),
Collectors.summingDouble(
firp -> firp.v2.getAmount().doubleValue()
)
)
)
)
);
Use SQL style CROSS APPLY instead
of flatMap()
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result =
Seq.seq(loadAllFilms())
.crossApply(f -> f.getInventories()) // <Film, Inventory>
.crossApply(fi -> fi.v2.getRentals()) // <<F, I>, Rental>
.crossApply(fir -> fir.v2.getPayments()) // <<<F, I>, R>, Payment>
.collect(
Collectors.groupingBy(firp -> firp.v1.v1.v1,
Collectors.groupingBy(firp -> firp.v1.v1.v2.getStoreId(),
Collectors.groupingBy(firp -> firp.v2.getPaymentDate(),
Collectors.summingDouble(
firp -> firp.v2.getAmount().doubleValue()
)
)
)
)
);
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result =
Seq.seq(loadAllFilms())
.crossApply(f -> f.getInventories())
.crossApply(fi -> fi.v2.getRentals())
.crossApply(fir -> fir.v2.getPayments())
.collect(
Collectors.groupingBy(firp -> firp.v1.v1.v1,
Collectors.groupingBy(firp -> firp.v1.v1.v2.getStoreId(),
Collectors.groupingBy(firp -> firp.v2.getPaymentDate(),
Collectors.summingDouble(
firp -> firp.v2.getAmount().doubleValue()
)
)
)
)
);
<<<Film, Inventory>, Rental>, Payment>
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result =
Seq.seq(loadAllFilms())
.crossApply(f -> f.getInventories())
.crossApply(fi -> fi.v2.getRentals().stream()
.flatMap(r -> r.getPayments().stream()))
.collect(
Collectors.groupingBy(fip -> fip.v1.v1,
Collectors.groupingBy(fip -> fip.v1.v2.getStoreId(),
Collectors.groupingBy(fip -> fip.v2.getPaymentDate(),
Collectors.summingDouble(
fip -> fip.v2.getAmount().doubleValue()
)
)
)
)
);
Hm, never really needed the rentals
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Film, Map<Integer, Map<LocalDate, Double>>> result =
Seq.seq(loadAllFilms())
.crossApply(f -> f.getInventories())
.crossApply(fi -> fi.v2.getRentals().stream()
.flatMap(r -> r.getPayments().stream()))
.collect(
Collectors.groupingBy(fip -> fip.v1.v1,
Collectors.groupingBy(fip -> fip.v1.v2.getStoreId(),
Collectors.groupingBy(fip -> fip.v2.getPaymentDate(),
Collectors.summingDouble(
fip -> fip.v2.getAmount().doubleValue()
)
)
)
)
);
A little bit better now...
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Tuple3<Film, Integer, LocalDate>, Double> result =
Seq.seq(loadAllFilms())
.crossApply(f -> f.getInventories())
.crossApply(fi -> fi.v2.getRentals().stream()
.flatMap(r -> r.getPayments().stream()))
.groupBy(
fip -> tuple(
fip.v1.v1,
fip.v1.v2.getStoreId(),
fip.v2.getPaymentDate()
),
Agg.sum(fip -> fip.v2.getAmount())
);
Oh, not that bad, actually
┬─┬ ノ( ゜-゜ノ)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Let’s try that Java algorithm again
Map<Tuple3<Film, Integer, LocalDate>, Double> result =
Seq.seq(loadAllFilms())
.crossApply(f -> f.getInventories())
.crossApply(fi -> fi.v2.getRentals().stream()
.flatMap(r -> r.getPayments().stream()))
.groupBy(
fip -> tuple(
fip.v1.v1,
fip.v1.v2.getStoreId(),
fip.v2.getPaymentDate()
),
Agg.sum(fip -> fip.v2.getAmount())
);
Result type a bit nicer, too
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Bad news is:
How much time did
we spend on this
problem now?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Remember this slide? Was it all that hard?
SELECT
title, store_id, payment_date,
SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, store_id, payment_date
ORDER BY title, store_id, payment_date
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Everyone understands now…
SQL is a 4GL
This means great
improvement of developer
productivity
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Everyone understands now…
How much time did I spend talking
about SQL so far?
How much time on Java?
SQL is easier = SQL is more productive
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What will I talk about?
• SQL is awesome
• SQL is productive
• SQL is fast
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Suspense!
Best chapter:
Performance
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
But first
How does SQL
work?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Business asking
How many films did each
actor whose last name
starts with «A» play in?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
They want this
Starts with «A»
How many films
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
This is the query. But what really happens?
SELECT
first_name, last_name, count(*)
FROM actor
JOIN film_actor USING (actor_id)
WHERE last_name LIKE 'A%'
GROUP BY first_name, last_name
ORDER BY count(*) DESC
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Logical Operations order
1. Load tables
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Logical Operations order
1. Load tables
Observe: «LOGICAL». Not «ACTUAL»
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Logical Operations order
1. Load tables
2. Apply predicates
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Logical Operations order
1. Load tables
2. Apply predicates
3. Collect groups
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Logical Operations order
1. Load tables
2. Apply predicates
3. Collect groups
4. Aggregate
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Logical Operations order
1. Load tables
2. Apply predicates
3. Collect groups
4. Aggregate
5. Project
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Logical Operations order
1. Load tables
2. Apply predicates
3. Collect groups
4. Aggregate
5. Project
6. Order
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Complete order
Logical operations order
1. FROM, JOIN, APPLY
2. WHERE
3. CONNECT BY (Oracle)
4. GROUP BY
5. Aggregations
6. HAVING
7. WINDOW
8. MODEL (Oracle)
9. SELECT
10. DISTINCT
11. UNION, INTERSECT, EXCEPT
12. ORDER BY
13. OFFSET
14. LIMIT
15. FOR UPDATE
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What’s the actual algorithm?
But that’s not what
really happens!
Any algorithm that produces
the same result is acceptable.
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What’s the actual algorithm?
Can we see the
actual algorithm?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
It’s called «execution plan»
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Who has seen an execution plan?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
SQL Developer
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
pgAdmin III
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
SQL Workbench
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
SQL Server Management Studio
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What’s the actual algorithm?
How many rows from operation
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What’s the actual algorithm?
How much time does it take
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Imperative
Actual operations order
1. Access ROWIDs from Index given the predicate
What’s the actual algorithm?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What’s the actual algorithm?
Imperative
Actual operations order
1. Access ROWIDs from Index given the predicate
2. Access other columns from the same row in the table
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What’s the actual algorithm?
Imperative
Actual operations order
1. Access ROWIDs from Index given the predicate
2. Access other columns from the same row in the table
3. Load foreign key relationship index into memory
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What’s the actual algorithm?
Imperative
Actual operations order
1. Access ROWIDs from Index given the predicate
2. Access other columns from the same row in the table
3. Load foreign key relationship index into memory
4. Put both data sets in hashmaps and join them
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What’s the actual algorithm?
Imperative
Actual operations order
1. Access ROWIDs from Index given the predicate
2. Access other columns from the same row in the table
3. Load foreign key relationship index into memory
4. Put both data sets in hashmaps and join them
5. Create another hashmap to group rows
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What’s the actual algorithm?
Imperative
Actual operations order
1. Access ROWIDs from Index given the predicate
2. Access other columns from the same row in the table
3. Load foreign key relationship index into memory
4. Put both data sets in hashmaps and join them
5. Create another hashmap to group rows
6. Sort the result
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Huh!
Declarative vs
Imperative
Would you have chosen the
same algorithm?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
E.g. Apparently, it’s faster in this
case to load 5462 rows into
memory than seeking 6 counts
individually...
Huh!
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Big O Notation
Hash join: O(N)
(N = film_actors (bigger table))
Nested loop join with indexes:
O(log M x log N)
(M = actors, N = film_actors)
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Hash join: O(N)
(N = film_actors (bigger table))
Nested loop join with indexes:
O(log M x log N)
(M = actors, N = film_actors)
Big O Notation
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Well...
It depends!
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What you think you have
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What you may really have
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What you may really have
«Works on my machine» ಠ_ಠ
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
More info
bigocheatsheet.com
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Statistics
Here’s an interesting
thing to think about:
Histograms
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Statistics
Histogram
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Statistics
Histogram
-- Predicate 1
WHERE amount BETWEEN -2000 AND 2000
-- Predicate 2
WHERE amount BETWEEN 5000 AND 9000
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Statistics
Histogram
-- Predicate 1
WHERE amount BETWEEN -2000 AND 2000
-- Predicate 2
WHERE amount BETWEEN 5000 AND 9000
Do both
predicates profit
from indexing?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Statistics
Histogram
-- Not very selective predicate
WHERE amount BETWEEN -2000 AND 2000
-- Very selective predicate
WHERE amount BETWEEN 5000 AND 9000
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Statistics
Histogram
-- Not very selective predicate
WHERE amount BETWEEN -2000 AND 2000
-- Very selective predicate
WHERE amount BETWEEN 5000 AND 9000
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Statistics
Accessing the index is only worth
the pain if it helps reduce the
result set
Otherwise, just read from the table
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Statistics
The database knows all these things.
• How many rows are returned from a table?
• From a query?
• How much does it cost to access the disk?
• The cache?
• How often is this query run?
• How often is the table accessed?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Statistics
The database knows all these things.
• How much memory do we have?
• How many processes are running in parallel right now?
• Is the operating system doing anything?
• How does the query perform with this bind variable?
• Are we running on an HDD or SSD or Flash or RAM?
• How many locks do we have on our rows?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Expression trees
Everything has a cost
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Expression trees
How does SQL work?
1. A parsed SQL string produces an expression tree
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
How does SQL work?
1. A parsed SQL string produces an expression tree
A + (A – B)
Expression trees
+
-A
A B
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Expression trees
How does SQL work?
1. A parsed SQL string produces an expression tree
2. Multiple expression trees are equivalent: They can be
transformed into each other
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
How does SQL work?
1. A parsed SQL string produces an expression tree
2. Multiple expression trees are equivalent: They can be
transformed into each other
A + (A – B)
Expression trees
+
-A
A B
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
How does SQL work?
1. A parsed SQL string produces an expression tree
2. Multiple expression trees are equivalent: They can be
transformed into each other
A + (A – B) (A + A) - B
Expression trees
+
-A
A B
+
-
A A
B
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
How does SQL work?
1. A parsed SQL string produces an expression tree
2. Multiple expression trees are equivalent: They can be
transformed into each other
A + (A – B) (2 * A) - B
Expression trees
+
-A
A B
*
-
2 A
B
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
How does SQL work?
1. A parsed SQL string produces an expression tree
2. Multiple expression trees are equivalent: They can be
transformed into each other
A + (A – B) (2 * A) - B
Expression trees
+
-A
A B
*
-
2 A
B
E.g.: Accessing A is super expensive
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Expression trees
How does SQL work?
1. A parsed SQL string produces an expression tree
2. Multiple expression trees are equivalent: They can be
transformed into each other
3. Each expression tree has a corresponding execution
plan and an associated, estimated cost
4. The «best» plan (= lowest estimated cost) is chosen
5. The actual execution cost is compared with the
estimate to improve future estimates
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Expression trees
How does SQL work?
1. A parsed SQL string produces an expression tree
2. Multiple expression trees are equivalent: They can be
transformed into each other
3. Each expression tree has a corresponding execution
plan and an associated, estimated cost
4. The «best» plan (= lowest estimated cost) is chosen
5. The actual execution cost is compared with the
estimate to improve future estimates
When’s the last time you wrote Java
code that did this?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Expression trees
Special treat:
Oracle 12c can abort and switch
execution plans «in flight». This is
called «Adaptive Execution Plans».
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
What will I talk about?
• SQL is awesome
• SQL is productive
• SQL is fast
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Why do I talk about SQL?
Now that you know
all of this...
What do you prefer?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
This?
Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...;
List<Film> films = nPlusOneLoadAllFilms(); // TODO
for (Film film : films) {
Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore =
result.computeIfAbsent(film, k -> new HashMap<>());
for (Inventory inventory : film.getInventories()) {
Map<LocalDate, BigDecimal> daily =
dailyPerStore.computeIfAbsent(
inventory.getStoreId(), k -> new HashMap());
for (Rental rental : inventory.getRentals())
for (Payment p : rental.getPayments())
daily.compute(
p.getPaymentDate(),
(k, v) -> v == null ? p.getAmount() : p.getAmount().add(v));
}
}
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Or, this?
SELECT
title, store_id, payment_date, SUM(amount)
FROM film
JOIN inventory USING (film_id)
JOIN rental USING (inventory_id)
JOIN payment USING (rental_id)
GROUP BY film_id, store_id, payment_date
ORDER BY title, store_id, payment_date
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Why do I talk about SQL?
SQL is the only ever successful,
mainstream, and general-
purpose 4GL (Fourth-
Generation Programming
Language)
And it is awesome!
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Why doesn’t anyone else talk about SQL?
¯_(シ)_/¯
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Can I write SQL in Java?
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Can I write SQL in Java? – Yes. With jOOQ
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Can I write SQL in Java? – Yes. With jOOQ
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Can I write SQL in Java? – Yes. With jOOQ
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
So what’s the key takeaway?
1. Can you do it in the database? Yes
2. Can you do it in the database? Yes
(... after visiting my 2 day SQL training)
3. Can you do it in your database? Yes
(... unless you're using MySQL)
4. Should you do it in the database? Yes
5. Do long talk titles attract attention? Yes
6. Will this talk ever end? Yes
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
If you haven’t had enough
Google «10 SQL Tricks»
and find the other talk’s
transcript
https://blog.jooq.org/2016/04/25/10-sql-
tricks-that-you-didnt-think-were-possible/
Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0
Thank you
Check out our trainings:
http://www.jooq.org/training
Coordinates
• Blog: http://blog.jooq.org (excellent Java SQL content)
• Twitter: @JavaOOQ / @lukaseder (more lame jokes)
• E-Mail: lukas.eder@datageekery.com
• Bank account: CH57 8148 7000 0SQL AWSM 7

More Related Content

Viewers also liked

10 SQL Tricks that You Didn't Think Were Possible
10 SQL Tricks that You Didn't Think Were Possible10 SQL Tricks that You Didn't Think Were Possible
10 SQL Tricks that You Didn't Think Were PossibleLukas Eder
 
Modern SQL in Open Source and Commercial Databases
Modern SQL in Open Source and Commercial DatabasesModern SQL in Open Source and Commercial Databases
Modern SQL in Open Source and Commercial DatabasesMarkus Winand
 
Zen and the Art of Writing SQL Query
Zen and the Art of Writing SQL QueryZen and the Art of Writing SQL Query
Zen and the Art of Writing SQL QueryPlamen Ratchev
 
Why relationships are cool but "join" sucks
Why relationships are cool but "join" sucksWhy relationships are cool but "join" sucks
Why relationships are cool but "join" sucksLuca Garulli
 
The Features That (maybe) You Didn't Know About
The Features That (maybe) You Didn't Know AboutThe Features That (maybe) You Didn't Know About
The Features That (maybe) You Didn't Know AboutOren Nakdimon
 
Efficient Pagination Using MySQL
Efficient Pagination Using MySQLEfficient Pagination Using MySQL
Efficient Pagination Using MySQLEvan Weaver
 
It was just Open Source - TEDx Novara
It was just Open Source - TEDx NovaraIt was just Open Source - TEDx Novara
It was just Open Source - TEDx NovaraFabio Mora
 
Intro to Graphs and Neo4j
Intro to Graphs and Neo4jIntro to Graphs and Neo4j
Intro to Graphs and Neo4jNeo4j
 
Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)Scott Wlaschin
 
Use of standards and related issues in predictive analytics
Use of standards and related issues in predictive analyticsUse of standards and related issues in predictive analytics
Use of standards and related issues in predictive analyticsPaco Nathan
 
Thirteen ways of looking at a turtle
Thirteen ways of looking at a turtleThirteen ways of looking at a turtle
Thirteen ways of looking at a turtleScott Wlaschin
 
Going Reactive with Spring 5 & Project Reactor
Going Reactive with Spring 5 & Project ReactorGoing Reactive with Spring 5 & Project Reactor
Going Reactive with Spring 5 & Project ReactorMark Heckler
 
Data Modeling with Neo4j
Data Modeling with Neo4jData Modeling with Neo4j
Data Modeling with Neo4jNeo4j
 
Hadoop security
Hadoop securityHadoop security
Hadoop securityBiju Nair
 
SQL Cockpit 3.1 - Overview
SQL Cockpit 3.1 - OverviewSQL Cockpit 3.1 - Overview
SQL Cockpit 3.1 - OverviewCadaxo GmbH
 
Introduction - Lecture 1 - Next Generation User Interfaces (4018166FNR)
Introduction - Lecture 1 - Next Generation User Interfaces (4018166FNR)Introduction - Lecture 1 - Next Generation User Interfaces (4018166FNR)
Introduction - Lecture 1 - Next Generation User Interfaces (4018166FNR)Beat Signer
 
WebSphere Message Broker Training | IBM WebSphere Message Broker Online Training
WebSphere Message Broker Training | IBM WebSphere Message Broker Online TrainingWebSphere Message Broker Training | IBM WebSphere Message Broker Online Training
WebSphere Message Broker Training | IBM WebSphere Message Broker Online Trainingecorptraining2
 

Viewers also liked (20)

10 SQL Tricks that You Didn't Think Were Possible
10 SQL Tricks that You Didn't Think Were Possible10 SQL Tricks that You Didn't Think Were Possible
10 SQL Tricks that You Didn't Think Were Possible
 
Modern SQL in Open Source and Commercial Databases
Modern SQL in Open Source and Commercial DatabasesModern SQL in Open Source and Commercial Databases
Modern SQL in Open Source and Commercial Databases
 
How to think like the engine
How to think like the engineHow to think like the engine
How to think like the engine
 
Zen and the Art of Writing SQL Query
Zen and the Art of Writing SQL QueryZen and the Art of Writing SQL Query
Zen and the Art of Writing SQL Query
 
Why relationships are cool but "join" sucks
Why relationships are cool but "join" sucksWhy relationships are cool but "join" sucks
Why relationships are cool but "join" sucks
 
The Features That (maybe) You Didn't Know About
The Features That (maybe) You Didn't Know AboutThe Features That (maybe) You Didn't Know About
The Features That (maybe) You Didn't Know About
 
Efficient Pagination Using MySQL
Efficient Pagination Using MySQLEfficient Pagination Using MySQL
Efficient Pagination Using MySQL
 
THE BIG PRINT - Showing the Action
THE BIG PRINT - Showing the ActionTHE BIG PRINT - Showing the Action
THE BIG PRINT - Showing the Action
 
It was just Open Source - TEDx Novara
It was just Open Source - TEDx NovaraIt was just Open Source - TEDx Novara
It was just Open Source - TEDx Novara
 
Intro to Graphs and Neo4j
Intro to Graphs and Neo4jIntro to Graphs and Neo4j
Intro to Graphs and Neo4j
 
Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)
 
Use of standards and related issues in predictive analytics
Use of standards and related issues in predictive analyticsUse of standards and related issues in predictive analytics
Use of standards and related issues in predictive analytics
 
Thirteen ways of looking at a turtle
Thirteen ways of looking at a turtleThirteen ways of looking at a turtle
Thirteen ways of looking at a turtle
 
Going Reactive with Spring 5 & Project Reactor
Going Reactive with Spring 5 & Project ReactorGoing Reactive with Spring 5 & Project Reactor
Going Reactive with Spring 5 & Project Reactor
 
Data Modeling with Neo4j
Data Modeling with Neo4jData Modeling with Neo4j
Data Modeling with Neo4j
 
Hadoop security
Hadoop securityHadoop security
Hadoop security
 
CouchDB Vs MongoDB
CouchDB Vs MongoDBCouchDB Vs MongoDB
CouchDB Vs MongoDB
 
SQL Cockpit 3.1 - Overview
SQL Cockpit 3.1 - OverviewSQL Cockpit 3.1 - Overview
SQL Cockpit 3.1 - Overview
 
Introduction - Lecture 1 - Next Generation User Interfaces (4018166FNR)
Introduction - Lecture 1 - Next Generation User Interfaces (4018166FNR)Introduction - Lecture 1 - Next Generation User Interfaces (4018166FNR)
Introduction - Lecture 1 - Next Generation User Interfaces (4018166FNR)
 
WebSphere Message Broker Training | IBM WebSphere Message Broker Online Training
WebSphere Message Broker Training | IBM WebSphere Message Broker Online TrainingWebSphere Message Broker Training | IBM WebSphere Message Broker Online Training
WebSphere Message Broker Training | IBM WebSphere Message Broker Online Training
 

Similar to How Modern SQL Databases Come up with Algorithms that You Would Have Never Dreamed Of

NoSQL? No, SQL! – How to Calculate Running Totals - Our Talk at the JUGS Bern
NoSQL? No, SQL! – How to Calculate Running Totals - Our Talk at the JUGS BernNoSQL? No, SQL! – How to Calculate Running Totals - Our Talk at the JUGS Bern
NoSQL? No, SQL! – How to Calculate Running Totals - Our Talk at the JUGS BernDataGeekery
 
Get Back in Control of Your SQL - #33rdDegree
Get Back in Control of Your SQL - #33rdDegreeGet Back in Control of Your SQL - #33rdDegree
Get Back in Control of Your SQL - #33rdDegreeDataGeekery
 
Best Way to Write SQL in Java
Best Way to Write SQL in JavaBest Way to Write SQL in Java
Best Way to Write SQL in JavaGerger
 
The jOOQ Talk at the JUG-HH in Hamburg, Jan 14, 2014
The jOOQ Talk at the JUG-HH in Hamburg, Jan 14, 2014The jOOQ Talk at the JUG-HH in Hamburg, Jan 14, 2014
The jOOQ Talk at the JUG-HH in Hamburg, Jan 14, 2014DataGeekery
 
Get Back in Control of your SQL with jOOQ - GeekOut by ZeroTurnaround
Get Back in Control of your SQL with jOOQ - GeekOut by ZeroTurnaroundGet Back in Control of your SQL with jOOQ - GeekOut by ZeroTurnaround
Get Back in Control of your SQL with jOOQ - GeekOut by ZeroTurnaroundDataGeekery
 
WIN203_With Amazon EC2 for Windows Server and Thinkbox Deadline
WIN203_With Amazon EC2 for Windows Server and Thinkbox DeadlineWIN203_With Amazon EC2 for Windows Server and Thinkbox Deadline
WIN203_With Amazon EC2 for Windows Server and Thinkbox DeadlineAmazon Web Services
 
"Developing with .NET Core on AWS", Martin Beeby, AWS Dev Day Kyiv 2019
"Developing with .NET Core on AWS", Martin Beeby, AWS Dev Day Kyiv 2019"Developing with .NET Core on AWS", Martin Beeby, AWS Dev Day Kyiv 2019
"Developing with .NET Core on AWS", Martin Beeby, AWS Dev Day Kyiv 2019Provectus
 
From Code to a Running Container | AWS Floor28
From Code to a Running Container | AWS Floor28From Code to a Running Container | AWS Floor28
From Code to a Running Container | AWS Floor28Amazon Web Services
 
Building Secure Services using Containers
Building Secure Services using ContainersBuilding Secure Services using Containers
Building Secure Services using ContainersAmazon Web Services
 
Scale Your Studio: Rendering with Spot and Deadline on AWS (CMP202) - AWS re:...
Scale Your Studio: Rendering with Spot and Deadline on AWS (CMP202) - AWS re:...Scale Your Studio: Rendering with Spot and Deadline on AWS (CMP202) - AWS re:...
Scale Your Studio: Rendering with Spot and Deadline on AWS (CMP202) - AWS re:...Amazon Web Services
 
SQL Training in Ambala ! Batra Computer Centre
SQL Training in Ambala ! Batra Computer CentreSQL Training in Ambala ! Batra Computer Centre
SQL Training in Ambala ! Batra Computer Centrejatin batra
 
CMP213_GPU(G3) Applications in Media and Entertainment Workloads
CMP213_GPU(G3) Applications in Media and Entertainment WorkloadsCMP213_GPU(G3) Applications in Media and Entertainment Workloads
CMP213_GPU(G3) Applications in Media and Entertainment WorkloadsAmazon Web Services
 
GPSTEC324_STORAGE FOR HPC IN THE CLOUD
GPSTEC324_STORAGE FOR HPC IN THE CLOUDGPSTEC324_STORAGE FOR HPC IN THE CLOUD
GPSTEC324_STORAGE FOR HPC IN THE CLOUDAmazon Web Services
 
GPS: Storage for HPC in the Cloud - GPSTEC324 - re:Invent 2017
GPS: Storage for HPC in the Cloud - GPSTEC324 - re:Invent 2017GPS: Storage for HPC in the Cloud - GPSTEC324 - re:Invent 2017
GPS: Storage for HPC in the Cloud - GPSTEC324 - re:Invent 2017Amazon Web Services
 
Speed up your Machine Learning workflows with built-in algorithms - Tel Aviv ...
Speed up your Machine Learning workflows with built-in algorithms - Tel Aviv ...Speed up your Machine Learning workflows with built-in algorithms - Tel Aviv ...
Speed up your Machine Learning workflows with built-in algorithms - Tel Aviv ...Amazon Web Services
 
Speed up your Machine Learning workflows with build-in algorithms
Speed up your Machine Learning workflows with build-in algorithmsSpeed up your Machine Learning workflows with build-in algorithms
Speed up your Machine Learning workflows with build-in algorithmsJulien SIMON
 
CI/CD with AWS Developer Tools and Fargate
CI/CD with AWS Developer Tools and FargateCI/CD with AWS Developer Tools and Fargate
CI/CD with AWS Developer Tools and FargateAmazon Web Services
 
Build Machine Learning Models with Amazon SageMaker (April 2019)
Build Machine Learning Models with Amazon SageMaker (April 2019)Build Machine Learning Models with Amazon SageMaker (April 2019)
Build Machine Learning Models with Amazon SageMaker (April 2019)Julien SIMON
 

Similar to How Modern SQL Databases Come up with Algorithms that You Would Have Never Dreamed Of (20)

NoSQL? No, SQL! – How to Calculate Running Totals - Our Talk at the JUGS Bern
NoSQL? No, SQL! – How to Calculate Running Totals - Our Talk at the JUGS BernNoSQL? No, SQL! – How to Calculate Running Totals - Our Talk at the JUGS Bern
NoSQL? No, SQL! – How to Calculate Running Totals - Our Talk at the JUGS Bern
 
Get Back in Control of Your SQL - #33rdDegree
Get Back in Control of Your SQL - #33rdDegreeGet Back in Control of Your SQL - #33rdDegree
Get Back in Control of Your SQL - #33rdDegree
 
Best Way to Write SQL in Java
Best Way to Write SQL in JavaBest Way to Write SQL in Java
Best Way to Write SQL in Java
 
MAE301_Boom for your Buck
MAE301_Boom for your BuckMAE301_Boom for your Buck
MAE301_Boom for your Buck
 
The jOOQ Talk at the JUG-HH in Hamburg, Jan 14, 2014
The jOOQ Talk at the JUG-HH in Hamburg, Jan 14, 2014The jOOQ Talk at the JUG-HH in Hamburg, Jan 14, 2014
The jOOQ Talk at the JUG-HH in Hamburg, Jan 14, 2014
 
Get Back in Control of your SQL with jOOQ - GeekOut by ZeroTurnaround
Get Back in Control of your SQL with jOOQ - GeekOut by ZeroTurnaroundGet Back in Control of your SQL with jOOQ - GeekOut by ZeroTurnaround
Get Back in Control of your SQL with jOOQ - GeekOut by ZeroTurnaround
 
WIN203_With Amazon EC2 for Windows Server and Thinkbox Deadline
WIN203_With Amazon EC2 for Windows Server and Thinkbox DeadlineWIN203_With Amazon EC2 for Windows Server and Thinkbox Deadline
WIN203_With Amazon EC2 for Windows Server and Thinkbox Deadline
 
"Developing with .NET Core on AWS", Martin Beeby, AWS Dev Day Kyiv 2019
"Developing with .NET Core on AWS", Martin Beeby, AWS Dev Day Kyiv 2019"Developing with .NET Core on AWS", Martin Beeby, AWS Dev Day Kyiv 2019
"Developing with .NET Core on AWS", Martin Beeby, AWS Dev Day Kyiv 2019
 
From Code to a Running Container | AWS Floor28
From Code to a Running Container | AWS Floor28From Code to a Running Container | AWS Floor28
From Code to a Running Container | AWS Floor28
 
Building Secure Services using Containers
Building Secure Services using ContainersBuilding Secure Services using Containers
Building Secure Services using Containers
 
Scale Your Studio: Rendering with Spot and Deadline on AWS (CMP202) - AWS re:...
Scale Your Studio: Rendering with Spot and Deadline on AWS (CMP202) - AWS re:...Scale Your Studio: Rendering with Spot and Deadline on AWS (CMP202) - AWS re:...
Scale Your Studio: Rendering with Spot and Deadline on AWS (CMP202) - AWS re:...
 
SQL Training in Ambala ! Batra Computer Centre
SQL Training in Ambala ! Batra Computer CentreSQL Training in Ambala ! Batra Computer Centre
SQL Training in Ambala ! Batra Computer Centre
 
CMP213_GPU(G3) Applications in Media and Entertainment Workloads
CMP213_GPU(G3) Applications in Media and Entertainment WorkloadsCMP213_GPU(G3) Applications in Media and Entertainment Workloads
CMP213_GPU(G3) Applications in Media and Entertainment Workloads
 
.NET on AWS
.NET on AWS.NET on AWS
.NET on AWS
 
GPSTEC324_STORAGE FOR HPC IN THE CLOUD
GPSTEC324_STORAGE FOR HPC IN THE CLOUDGPSTEC324_STORAGE FOR HPC IN THE CLOUD
GPSTEC324_STORAGE FOR HPC IN THE CLOUD
 
GPS: Storage for HPC in the Cloud - GPSTEC324 - re:Invent 2017
GPS: Storage for HPC in the Cloud - GPSTEC324 - re:Invent 2017GPS: Storage for HPC in the Cloud - GPSTEC324 - re:Invent 2017
GPS: Storage for HPC in the Cloud - GPSTEC324 - re:Invent 2017
 
Speed up your Machine Learning workflows with built-in algorithms - Tel Aviv ...
Speed up your Machine Learning workflows with built-in algorithms - Tel Aviv ...Speed up your Machine Learning workflows with built-in algorithms - Tel Aviv ...
Speed up your Machine Learning workflows with built-in algorithms - Tel Aviv ...
 
Speed up your Machine Learning workflows with build-in algorithms
Speed up your Machine Learning workflows with build-in algorithmsSpeed up your Machine Learning workflows with build-in algorithms
Speed up your Machine Learning workflows with build-in algorithms
 
CI/CD with AWS Developer Tools and Fargate
CI/CD with AWS Developer Tools and FargateCI/CD with AWS Developer Tools and Fargate
CI/CD with AWS Developer Tools and Fargate
 
Build Machine Learning Models with Amazon SageMaker (April 2019)
Build Machine Learning Models with Amazon SageMaker (April 2019)Build Machine Learning Models with Amazon SageMaker (April 2019)
Build Machine Learning Models with Amazon SageMaker (April 2019)
 

Recently uploaded

Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Developmentvyaparkranti
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptrcbcrtm
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 

Recently uploaded (20)

Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Development
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.ppt
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 

How Modern SQL Databases Come up with Algorithms that You Would Have Never Dreamed Of

  • 1. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 NoSQL? No, SQL! How Modern SQL Databases Come up with Algorithms that You Would Have Never Dreamed Of
  • 2. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 NoSQL? No, SQL! TL;DR: SQL = Awesome
  • 3. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Why are you here? Because: … This cannot be true … This must not be true … Is it true, though? … OMG imma rewrite all code to SQL
  • 4. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Me – @lukaseder SQL is a device whose mystery is only exceeded by its power! - Founder and CEO at Data Geekery - Oracle Java Champion - JUG.ch Board Member
  • 5. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 When you leave the room
  • 6. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Why do I talk about SQL? SQL is the only ever successful, mainstream, and general- purpose 4GL (Fourth- Generation Programming Language) And it is awesome!
  • 7. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Why doesn’t anyone else talk about SQL?
  • 8. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Why doesn’t anyone else talk about SQL? ¯_(シ)_/¯
  • 9. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Why doesn’t anyone else talk about SQL? Except Vlad
  • 10. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Vlad shows JPA’s only important feature His blog: http://tiny.cc/jpa-only-useful-feature Vlad: Hibernate Developer Advocate
  • 11. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Vlad shows JPA’s only important feature His blog: http://tiny.cc/jpa-only-useful-feature Vlad: Hibernate Developer Advocate
  • 12. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What is SQL? Who has seen my other talk?
  • 13. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What is SQL? I mean this one
  • 14. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 10 SQL tricks to convince you SQL is awesome
  • 15. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 10 SQL tricks to convince you SQL is awesome Not that hard to find
  • 16. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 A SQL trick -- Query from http://explainextended.com/2013/12/31/happy-new-year-5/ WITH RECURSIVE q(r, i, rx, ix, g) AS ( SELECT r::DOUBLE PRECISION * 0.02, i::DOUBLE PRECISION * 0.02, .0::DOUBLE PRECISION , .0::DOUBLE PRECISION, 0 FROM generate_series(-60, 20) r, generate_series(-50, 50) i UNION ALL SELECT r, i, CASE WHEN abs(rx * rx + ix * ix) <= 2 THEN rx * rx - ix * ix END + r, CASE WHEN abs(rx * rx + ix * ix) <= 2 THEN 2 * rx * ix END + i, g + 1 FROM q WHERE rx IS NOT NULL AND g < 99 ) SELECT array_to_string(array_agg(s ORDER BY r), '') FROM ( SELECT i, r, substring(' .:-=+*#%@', max(g) / 10 + 1, 1) s FROM q GROUP BY i, r ) q GROUP BY i ORDER BY i
  • 17. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 A SQL trick: Generating the Mandelbrot Set -- Query from http://explainextended.com/2013/12/31/happy-new-year-5/ WITH RECURSIVE q(r, i, rx, ix, g) AS ( SELECT r::DOUBLE PRECISION * 0.02, i::DOUBLE PRECISION * 0.02, .0::DOUBLE PRECISION , .0::DOUBLE PRECISION, 0 FROM generate_series(-60, 20) r, generate_series(-50, 50) i UNION ALL SELECT r, i, CASE WHEN abs(rx * rx + ix * ix) <= 2 THEN rx * rx - ix * ix END + r, CASE WHEN abs(rx * rx + ix * ix) <= 2 THEN 2 * rx * ix END + i, g + 1 FROM q WHERE rx IS NOT NULL AND g < 99 ) SELECT array_to_string(array_agg(s ORDER BY r), '') FROM ( SELECT i, r, substring(' .:-=+*#%@', max(g) / 10 + 1, 1) s FROM q GROUP BY i, r ) q GROUP BY i ORDER BY i
  • 18. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 But today… But today, we’ll talk about more basic SQL
  • 19. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 But today… But today, we’ll talk about more basic SQL (still awesome)
  • 20. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 But today… Is this SQL?
  • 21. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Who can handle this SQL statement here? SELECT * FROM person WHERE id = 42
  • 22. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Easy stuff Perfect This talk is for you.
  • 23. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What will I talk about? • SQL is awesome • SQL is productive • SQL is fast
  • 24. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What will I talk about? • SQL is awesome • SQL is productive • SQL is fast
  • 25. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 There are two ways of proving this 1. By example 2. By alternative (Java)
  • 26. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Disclaimer This is going to be a high level, conceptual story about SQL We’re not going into deeper levels.
  • 27. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Business is asking What is the daily revenue of each store
  • 28. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Business is asking
  • 29. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Business is asking
  • 30. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Business is asking What is the daily revenue of each store
  • 31. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Business is asking What is the daily revenue of each store Film Money Day JOIN
  • 32. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 No problemo
  • 33. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Easy, right? SELECT title, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, payment_date ORDER BY title, payment_date
  • 34. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Easy, right? SELECT title, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, payment_date ORDER BY title, payment_date Money per film
  • 35. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Easy, right? SELECT title, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, payment_date ORDER BY title, payment_date Relationship film ↔ money
  • 36. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Easy, right? SELECT title, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, payment_date ORDER BY title, payment_date Aggregation per film / date
  • 37. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Imperative style Let’s write this in «classic» Java
  • 38. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 “Classic Java”
  • 39. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s get rolling class Film { }
  • 40. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s get rolling You still with me?
  • 41. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Obviously, Film is a tuple class Film { int filmId; String title; }
  • 42. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Because, Java class Film { int filmId; String title; int getFilmId() { return filmId; } ... }
  • 43. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Never forget these, of course class Film { int filmId; String title; int getFilmId() { ... } void setFilmId(int filmId) { ... } String getTitle() { ... } void setTitle(String title) { ... } int hashCode() { ... } boolean equals(Object o) { ... } String toString() { ... } ... }
  • 44. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Abstractions, ladies and gentlemen! class FilmFactory { Film newFilm() { ... } } class FilmFactoryBuilder { FilmFactory newFilmFactory() { ... } }
  • 45. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Abstractions, ladies and gentlemen! interface FilmFactory { Film newFilm(); } interface FilmFactoryBuilder { FilmFactory newFilmFactory(); }
  • 46. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Just to be sure, super generic! interface FilmFactory { Film newFilm(); } interface FilmFactoryBuilder { FilmFactory newFilmFactory(); } class FilmFactoryImpl { @Override public Film newFilm() { ... } } class FilmFactoryBuilderImpl { @Override public FilmFactory newFilmFactory() { ... } }
  • 47. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Some Spring interface FilmFactory { Film newFilm(); } interface FilmFactoryBuilder { FilmFactory newFilmFactory(); } @Bean class FilmFactoryImpl { @Override public Film newFilm() { ... } } @Bean class FilmFactoryBuilderImpl { @Override @EnableCaching public FilmFactory newFilmFactory() { ... } }
  • 48. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Some Spring, and a little Lombok @FunctionalInterface interface FilmFactory { Film newFilm(); } @FunctionalInterface interface FilmFactoryBuilder { FilmFactory newFilmFactory(); } @Bean @EnableAspectJAutoProxy @EnableAutoConfiguration class FilmFactoryImpl { @Override public Film newFilm() { ... } } @Bean @Configuration @NoArgsConstructor class FilmFactoryBuilderImpl { @Override @EnableCaching public FilmFactory newFilmFactory() { ... } }
  • 49. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Oh, what the heck @FunctionalInterface interface FilmFactory { Film newFilm(); } @FunctionalInterface interface FilmFactoryBuilder { FilmFactory newFilmFactory(); } @Bean @EnableAspectJAutoProxy @EnableAutoConfiguration class FilmFactoryImpl { @Override public Film newFilm() { ... } } @Bean @Configuration @NoArgsConstructor @Cloneable @SneakyThrows @ResultSetMapping @ConcurrentInitialiserProxyFactory @SpringPrefetchAdapter @AdapterProxyBeanMethod @AdapterBeanProxyMethod class FilmFactoryBuilderImpl { @Override @EnableCaching public FilmFactory newFilmFactory() { ... } }
  • 50. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Oh, what the heck @FunctionalInterface interface FilmFactory { Film newFilm(); } @FunctionalInterface interface FilmFactoryBuilder { FilmFactory newFilmFactory(); } @Bean @EnableAspectJAutoProxy @EnableAutoConfiguration class FilmFactoryImpl { @Override @ThisMethodDidntHaveAnnotationsYet @OKWeStillHaveSomeSpaceLeft @LetsSeeIfWeCanReachThePrintMargin public Film newFilm() { ... } } @Bean @Configuration @NoArgsConstructor @Cloneable @SneakyThrows @ResultSetMapping @ConcurrentInitialiserProxyFactory @SpringPrefetchAdapter @AdapterProxyBeanMethod @AdapterBeanProxyMethod @MoreAndMoreAnnotations @CanYouEvenReadThis @IsThereStillAnyRealLogicLeft @ThisJokeNeverGetsLame @Annotatiomania @WhoWillBeNextYearsAnnotatiomaniac class FilmFactoryBuilderImpl { @Override @EnableCaching public FilmFactory newFilmFactory() { ... } }
  • 51. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Average enterprise bean is visible from space @FunctionalInterface interface FilmFactory { Film newFilm(); } @FunctionalInterface @NoArgsConstructor @Cloneable @SneakyThrows interface FilmFactoryBuilder { FilmFactory newFilmFactory(); } @Bean @EnableAspectJAutoProxy @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows @EnableAutoConfiguration @NoArgsConstructor @Cloneable @SneakyThrows class FilmFactoryImpl { @Override @NoArgsConstructor @Cloneable @SneakyThrows @ThisMethodDidntHaveAnnotationsYet @OKWeStillHaveSomeSpaceLeft @LetsSeeIfWeCanReachThePrintMargin public Film newFilm() { ... } } @Bean @Configuration @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows @ResultSetMapping @ConcurrentInitialiserProxyFactory @SpringPrefetchAdapter @AdapterProxyBeanMethod @AdapterBeanProxyMethod @NoArgsConstructor @Cloneable @SneakyThrows @MoreAndMoreAnnotations @CanYouEvenReadThis @NoArgsConstructor @Cloneable @SneakyThrows @IsThereStillAnyRealLogicLeft @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows @ThisJokeNeverGetsLame @Annotatiomania @WhoWillBeNextYearsAnnotatiomaniac class FilmFactoryBuilderImpl { @Override @EnableCaching public FilmFactory newFilmFactory() { ... } }
  • 52. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Enough of this. More info here www.annotatiomania.com
  • 53. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Hmm, relationships? class Film { int filmId; String title; int getFilmId() { ... } void setFilmId(int filmId) { ... } String getTitle() { ... } void setTitle(String title) { ... } // Hmm... Inventory? Store? Rental? Payment? int hashCode() { ... } boolean equals(Object o) { ... } String toString() { ... } ... }
  • 54. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s assume, we copy relational model 1:1 class Film { int filmId; String title; int getFilmId() { ... } void setFilmId(int filmId) { ... } String getTitle() { ... } void setTitle(String title) { ... } List<Inventory> getInventories() { ... } int hashCode() { ... } boolean equals(Object o) { ... } String toString() { ... } ... }
  • 55. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s assume, we copy relational model 1:1 class Film { int filmId; String title; int getFilmId() { ... } void setFilmId(int filmId) { ... } String getTitle() { ... } void setTitle(String title) { ... } @OneToMany(mappedBy = "film") List<Inventory> getInventories() { ... } int hashCode() { ... } boolean equals(Object o) { ... } String toString() { ... } ... }
  • 56. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s assume, we copy relational model 1:1 class Film { int filmId; String title; int getFilmId() { ... } void setFilmId(int filmId) { ... } String getTitle() { ... } void setTitle(String title) { ... } @OneToMany(mappedBy = "film") List<Inventory> getInventories() { ... } int hashCode() { ... } boolean equals(Object o) { ... } String toString() { ... } ... } Anyone seen these lovely things?
  • 57. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s assume, we copy relational model 1:1 class Film { int filmId; String title; int getFilmId() { ... } void setFilmId(int filmId) { ... } String getTitle() { ... } void setTitle(String title) { ... } @OneToMany(mappedBy = "film", fetch = FetchType.EAGER) List<Inventory> getInventories() { ... } int hashCode() { ... } boolean equals(Object o) { ... } String toString() { ... } ... } How about this? Care discuss this?
  • 58. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s assume, we copy relational model 1:1 class Film { int filmId; String title; int getFilmId() { ... } void setFilmId(int filmId) { ... } String getTitle() { ... } void setTitle(String title) { ... } @OneToMany(mappedBy = "film", fetch = FetchType.LAZY) List<Inventory> getInventories() { ... } int hashCode() { ... } boolean equals(Object o) { ... } String toString() { ... } ... } How about this? Care discuss this?
  • 59. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 If you must @OneToMany Ask Vlad
  • 60. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Now, calculate. This be the result type // This is the optimal result type Map<Film, Map<LocalDate, BigDecimal>> result = new HashMap<>();
  • 61. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Now, calculate. This be the result type // This is the optimal result type Map<Film, Map<LocalDate, BigDecimal>> result = new HashMap<>(); Money Per film Per date
  • 62. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Money, eh? JSR 354 FTW! (Java Money API)
  • 63. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Money, eh? JSR 354 FTW! (Java Money API)
  • 64. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Now, calculate. This be the result type // This is the optimal result type Map<Film, Map<LocalDate, BigDecimal>> result = new HashMap<>();
  • 65. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Now, calculate. Wait… // Or this? Map<Film, Map<LocalDate, BigDecimal>> result = new LinkedHashMap<>();
  • 66. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Now, calculate. Or better // Or maybe this? SortedMap<Film, SortedMap<LocalDate, BigDecimal>> result = new TreeMap<>();
  • 67. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Now, calculate. Aagh // Kewl, wrote some library MultiKeyMap< Film, LocalDate, BigDecimal> result = new MultiKeyMap<>();
  • 68. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Five hours later
  • 69. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Who in here has felt this way before?
  • 70. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Now let’s calculate, for real Map<Film, Map<LocalDate, BigDecimal>> result = ...;
  • 71. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Easy, so far Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO
  • 72. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Easy, so far Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO // FIXME 2002-04-01 Will optimize this later
  • 73. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Easy, so far Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO // FIXME 2003-04-01 Will optimize this “later”
  • 74. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Easy, so far Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO // FIXME 2003-04-01 Will optimize this “later” // FIXME 2005-04-01 URGENT! This is really slow!
  • 75. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Still following? Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) ; // TODO
  • 76. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Still following? Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); // TODO }
  • 77. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Still following? Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); // TODO }
  • 78. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Aaah, lazy initialization! Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { daily = new HashMap<>(); result.put(film, daily); } // TODO }
  • 79. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Aaah, lazy initialization! Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { daily = new HashMap<>(); result.put(film, daily); } // TODO }
  • 80. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s have that Map discussion again Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { daily = new LinkedHashMap<>(); // TODO: Better Map! result.put(film, daily); } // TODO }
  • 81. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 OK, next Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { ... } // TODO }
  • 82. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 OK, now looping Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { ... } for (Inventory inventory : film.getInventories()) ; // TODO }
  • 83. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 OK, now looping Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { ... } for (Inventory inventory : film.getInventories()) for (Rental rental : inventory.getRentals()) ; // TODO }
  • 84. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 OK, now looping Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { ... } for (Inventory inventory : film.getInventories()) for (Rental rental : inventory.getRentals()) for (Payment payment : rental.getPayments()) ; // TODO }
  • 85. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 OK, now looping Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { ... } for (Inventory inventory : film.getInventories()) for (Rental rental : inventory.getRentals()) for (Payment payment : rental.getPayments()) ; // TODO } EAGER or LAZY?
  • 86. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 OK, now looping Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { ... } for (Inventory inventory : film.getInventories()) for (Rental rental : inventory.getRentals()) for (Payment payment : rental.getPayments()) ; // TODO } Or, entity graph?
  • 87. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Entity Graph – How JPA folks write SQL @NamedEntityGraph( name = "graph.film.inventories.rentals.payments", attributeNodes = @NamedAttributeNode( value = "inventories", subgraph = "inventories" ), subgraphs = { @NamedSubgraph( name = "inventories", attributeNodes = @NamedAttributeNode( value = "rentals", subgraph = "rentals" ) ), ... } )
  • 88. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Entity Graph – How JPA folks write SQL @NamedEntityGraph( name = "graph.film.inventories.rentals.payments", attributeNodes = @NamedAttributeNode( value = "inventories", subgraph = "inventories" ), subgraphs = { @NamedSubgraph( name = "inventories", attributeNodes = @NamedAttributeNode( value = "rentals", subgraph = "rentals" ) ), ... } )
  • 89. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Remember this slide? @FunctionalInterface interface FilmFactory { Film newFilm(); } @FunctionalInterface @NoArgsConstructor @Cloneable @SneakyThrows interface FilmFactoryBuilder { FilmFactory newFilmFactory(); } @Bean @EnableAspectJAutoProxy @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows @EnableAutoConfiguration @NoArgsConstructor @Cloneable @SneakyThrows class FilmFactoryImpl { @Override @NoArgsConstructor @Cloneable @SneakyThrows @ThisMethodDidntHaveAnnotationsYet @OKWeStillHaveSomeSpaceLeft @LetsSeeIfWeCanReachThePrintMargin public Film newFilm() { ... } } @Bean @Configuration @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows @ResultSetMapping @ConcurrentInitialiserProxyFactory @SpringPrefetchAdapter @AdapterProxyBeanMethod @AdapterBeanProxyMethod @NoArgsConstructor @Cloneable @SneakyThrows @MoreAndMoreAnnotations @CanYouEvenReadThis @NoArgsConstructor @Cloneable @SneakyThrows @IsThereStillAnyRealLogicLeft @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows @ThisJokeNeverGetsLame @Annotatiomania @WhoWillBeNextYearsAnnotatiomaniac class FilmFactoryBuilderImpl { @Override @EnableCaching public FilmFactory newFilmFactory() { ... } }
  • 90. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Your code now visible from Andromeda Galaxy @FunctionalInterface interface FilmFactory { Film newFilm(); } @FunctionalInterface @NoArgsConstructor @Cloneable @SneakyThrows interface FilmFactoryBuilder { FilmFactory newFilmFactory(); } @Bean @EnableAspectJAutoProxy @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows @EnableAutoConfiguration @NoArgsConstructor @Cloneable @SneakyThrows class FilmFactoryImpl { @Override @NoArgsConstructor @Cloneable @SneakyThrows @ThisMethodDidntHaveAnnotationsYet @OKWeStillHaveSomeSpaceLeft @LetsSeeIfWeCanReachThePrintMargin public Film newFilm() { ... } } @Bean @Configuration @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows @ResultSetMapping @ConcurrentInitialiserProxyFactory @SpringPrefetchAdapter @AdapterProxyBeanMethod @AdapterBeanProxyMethod @NoArgsConstructor @Cloneable @SneakyThrows @MoreAndMoreAnnotations @CanYouEvenReadThis @NoArgsConstructor @Cloneable @SneakyThrows @IsThereStillAnyRealLogicLeft @NoArgsConstructor @Cloneable @SneakyThrows @NoArgsConstructor @Cloneable @SneakyThrows @ThisJokeNeverGetsLame @Annotatiomania @WhoWillBeNextYearsAnnotatiomaniac class FilmFactoryBuilderImpl { @Override @EnableCaching public FilmFactory newFilmFactory() { ... } }
  • 91. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 OK, now looping, done. Right? Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { ... } for (Inventory inventory : film.getInventories()) for (Rental rental : inventory.getRentals()) for (Payment payment : rental.getPayments()) daily.put( payment.getPaymentDate(), payment.getAmount()); }
  • 92. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 OK, now looping, done. Wrong! Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.get(film); if (daily == null) { ... } for (Inventory inventory : film.getInventories()) for (Rental rental : inventory.getRentals()) for (Payment payment : rental.getPayments()) { LocalDate date = payment.getPaymentDate(); BigDecimal amount = payment.getAmount(); if (daily.containsKey(date)) daily.put(date, daily.get(date).add(amount)); else daily.put(date, amount); } }
  • 93. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 OK, now looping, done. OK, better with Java 8 Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.computeIfAbsent(film, k -> new HashMap<>()); for (Inventory inventory : film.getInventories()) for (Rental rental : inventory.getRentals()) for (Payment payment : rental.getPayments()) daily.compute( payment.getPaymentDate(), (k, v) -> v == null ? payment.getAmount() : payment.getAmount().add(v)); }
  • 94. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Feel good about yourself?
  • 95. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Business is asking again
  • 96. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Programmer reactions SQL Developer Java Developer
  • 97. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 SQL dev: I knew this was coming! SELECT title, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, payment_date ORDER BY title, payment_date
  • 98. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 SQL dev: Swoosh! SELECT title, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, payment_date ORDER BY title, payment_date
  • 99. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 SQL dev: Joke’s on you! SELECT title, store_id, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, store_id, payment_date ORDER BY title, store_id, payment_date
  • 100. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Java dev: Gaaah, OK Map<Film, Map<LocalDate, BigDecimal>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.computeIfAbsent(film, k -> new HashMap<>()); for (Inventory inventory : film.getInventories()) for (Rental rental : inventory.getRentals()) for (Payment p : rental.getPayments()) daily.compute( p.getPaymentDate(), (k, v) -> v == null ? p.getAmount() : p.getAmount().add(v)); }
  • 101. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Java dev: Let’s make some room Map<Film, Map<LocalDate, BigDecimal> > result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<LocalDate, BigDecimal> daily = result.computeIfAbsent(film, k -> new HashMap<>()); for (Inventory inventory : film.getInventories()) for (Rental rental : inventory.getRentals()) for (Payment p : rental.getPayments()) daily.compute( p.getPaymentDate(), (k, v) -> v == null ? p.getAmount() : p.getAmount().add(v)); }
  • 102. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Java dev: Let’s see, if I tweak this and then… Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore = result.computeIfAbsent(film, k -> new HashMap<>()); for (Inventory inventory : film.getInventories()) { Map<LocalDate, BigDecimal> daily = dailyPerStore.computeIfAbsent( inventory.getStoreId(), k -> new HashMap()); for (Rental rental : inventory.getRentals()) for (Payment p : rental.getPayments()) daily.compute( p.getPaymentDate(), (k, v) -> v == null ? p.getAmount() : p.getAmount().add(v)); } }
  • 103. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Java dev: Let’s see, if I tweak this and then… Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore = result.computeIfAbsent(film, k -> new HashMap<>()); for (Inventory inventory : film.getInventories()) { Map<LocalDate, BigDecimal> daily = dailyPerStore.computeIfAbsent( inventory.getStoreId(), k -> new HashMap()); for (Rental rental : inventory.getRentals()) for (Payment p : rental.getPayments()) daily.compute( p.getPaymentDate(), (k, v) -> v == null ? p.getAmount() : p.getAmount().add(v)); } }Architect: (that’s this guy)
  • 104. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Java dev: Let’s see, if I tweak this and then… Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore = result.computeIfAbsent(film, k -> new HashMap<>()); for (Inventory inventory : film.getInventories()) { Map<LocalDate, BigDecimal> daily = dailyPerStore.computeIfAbsent( inventory.getStoreId(), k -> new HashMap()); for (Rental rental : inventory.getRentals()) for (Payment p : rental.getPayments()) daily.compute( p.getPaymentDate(), (k, v) -> v == null ? p.getAmount() : p.getAmount().add(v)); } }Architect: We can’t have such types. Factor out in a new class. And Factory
  • 105. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore = result.computeIfAbsent(film, k -> new HashMap<>()); for (Inventory inventory : film.getInventories()) { Map<LocalDate, BigDecimal> daily = dailyPerStore.computeIfAbsent( inventory.getStoreId(), k -> new HashMap()); for (Rental rental : inventory.getRentals()) for (Payment p : rental.getPayments()) daily.compute( p.getPaymentDate(), (k, v) -> v == null ? p.getAmount() : p.getAmount().add(v)); } } And you’re like…
  • 106. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Meanwhile… While you and your architect engage in nominal vs structural typing philosophies...
  • 107. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Meanwhile… The inevitable
  • 108. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What on earth is a cumulative sum??
  • 109. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What on earth is a cumulative sum??
  • 110. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What on earth is a cumulative sum??
  • 111. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Java dev: 😵 // Thanks God it’s Friday! throw new UnsupportedOperationException();
  • 112. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Meanwhile, the SQL developer… SELECT title, store_id, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, store_id, payment_date ORDER BY title, store_id, payment_date
  • 113. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Meanwhile, the SQL developer… SELECT title, store_id, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, store_id, payment_date ORDER BY title, store_id, payment_date
  • 114. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Meanwhile, the SQL developer… SELECT title, store_id, payment_date, SUM(SUM(amount)) OVER ( PARTITION BY title, store_id ORDER BY payment_date ) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, store_id, payment_date ORDER BY title, store_id, payment_dateWindow function
  • 115. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What does it do?
  • 116. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 3GL vs. 4GL Do you get the message?
  • 117. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 3GL vs. 4GL SQL is a 4GL
  • 118. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 3GL vs. 4GL In SQL, we only declare the result.
  • 119. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 3GL vs. 4GL The database will figure out the algorithm for us.
  • 120. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 3GL vs. 4GL Algorithms are boring (mostly)
  • 121. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 3GL vs. 4GL We don’t care about • Writing algorithms (using them is a different story) • Premature Optimisation • Data type details (HashMap<A, B> or List<Entry<A, B>>?) • Local variables • Caches • Loops • Initialisation (or NullPointerException)
  • 122. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 3GL vs. 4GL We do care about • Business logic • Just a bit of indexing That’s it!
  • 123. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Is Java 8 Streams “declarative” ? The Stream API looks a lot like SQL’s declarative style
  • 124. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Is Java 8 Streams “declarative” ? The Stream API looks a lot like SQL’s declarative style FROM WHERE FETCH NEXT GROUP BY
  • 125. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 In a way, it’s very similar TABLE : Stream<Tuple<..>> SELECT : map() DISTINCT : distinct() JOIN : flatMap() WHERE / HAVING : filter() GROUP BY : collect() ORDER BY : sorted() UNION ALL : concat() See: http://blog.jooq.org/2015/08/13/common-sql-clauses-and-their-equivalents-in-java-8-streams/
  • 126. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...; List<Film> films = loadAllFilms(); // TODO for (Film film : films) { Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore = result.computeIfAbsent(film, k -> new HashMap<>()); for (Inventory inventory : film.getInventories()) { Map<LocalDate, BigDecimal> daily = dailyPerStore.computeIfAbsent( inventory.getStoreId(), k -> new HashMap()); for (Rental rental : inventory.getRentals()) for (Payment p : rental.getPayments()) daily.compute( p.getPaymentDate(), (k, v) -> v == null ? p.getAmount() : p.getAmount().add(v)); } }
  • 127. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms() .stream() .flatMap(f -> f.getInventories().stream()) .flatMap(i -> i.getRentals().stream()) .flatMap(r -> r.getPayments().stream()) .collect(... /* amount per film and store */ ...);
  • 128. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms() .stream() // Stream<Film> .flatMap(f -> f.getInventories().stream()) // Stream<Inventory> .flatMap(i -> i.getRentals().stream()) // Stream<Rental> .flatMap(r -> r.getPayments().stream()) // Stream<Payment> .collect(... /* amount per film and store */ ...);
  • 129. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms() .stream() // Stream<Film> .flatMap(f -> f.getInventories().stream()) // Stream<Inventory> .flatMap(i -> i.getRentals().stream()) // Stream<Rental> .flatMap(r -> r.getPayments().stream()) // Stream<Payment> .collect(... /* amount per film and store */ ...); How to access «f» and «i» in the Collector?
  • 130. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms() .stream() .flatMap(f -> f.getInventories().stream().map(i -> entry(f, i))) .flatMap(fi -> fi.v2.getRentals().stream().map(r -> entry(fi, r))) .flatMap(fir -> fir.v3.getPayments().stream().map(p -> entry(fir, p))) .collect(... /* amount per film and store */ ...); Use some wrapper types and pray for stack allocation to happen
  • 131. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms() .stream() .flatMap(f -> f.getInventories().stream().map(i -> entry(f, i))) .flatMap(fi -> fi.v2.getRentals().stream().map(r -> entry(fi, r))) .flatMap(fir -> fir.v3.getPayments().stream().map(p -> entry(fir, p))) .collect( Collectors.groupingBy(firp -> firp.getKey().getKey().getKey(), Collectors.groupingBy(firp -> firp.getKey().getKey().getValue() .getStoreId(), Collectors.groupingBy(firp -> firp.getValue().getPaymentDate(), Collectors.summingDouble( firp -> firp.getValue().getAmount().doubleValue() ) ) ) ) );
  • 132. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms() .stream() .flatMap(f -> f.getInventories().stream().map(i -> entry(f, i))) .flatMap(fi -> fi.v2.getRentals().stream().map(r -> entry(fi, r))) .flatMap(fir -> fir.v3.getPayments().stream().map(p -> entry(fir, p))) .collect( Collectors.groupingBy(firp -> firp.getKey().getKey().getKey(), Collectors.groupingBy(firp -> firp.getKey().getKey().getValue() .getStoreId(), Collectors.groupingBy(firp -> firp.getValue().getPaymentDate(), Collectors.summingDouble( firp -> firp.getValue().getAmount().doubleValue() ) ) ) ) ); But what the hell is this? (╯°□°)╯︵ ┻━┻
  • 133. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Well, it certainly looks declarative
  • 134. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 We can do a bit better, though Better Streams: https://github.com/jOOQ/jOOL
  • 135. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 We can do a bit better, though Seq.seq(persons) .collect( count(), max(Person::getAge), min(Person::getHeight), avg(Person::getWeight) ); // (3, Optional[35], // Optional[1.69], Optional[70.0])
  • 136. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = loadAllFilms() .stream() .flatMap(f -> f.getInventories().stream().map(i -> entry(f, i))) .flatMap(fi -> fi.v2.getRentals().stream().map(r -> entry(fi, r))) .flatMap(fir -> fir.v3.getPayments().stream().map(p -> entry(fir, p))) .collect( Collectors.groupingBy(firp -> firp.getKey().getKey().getKey(), Collectors.groupingBy(firp -> firp.getKey().getKey().getValue() .getStoreId(), Collectors.groupingBy(firp -> firp.getValue().getPaymentDate(), Collectors.summingDouble( firp -> firp.getValue().getAmount().doubleValue() ) ) ) ) );
  • 137. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = Seq.seq(loadAllFilms()) .flatMap(f -> f.getInventories().stream().map(i -> entry(f, i))) .flatMap(fi -> fi.v2.getRentals().stream().map(r -> entry(fi, r))) .flatMap(fir -> fir.v3.getPayments().stream().map(p -> entry(fir, p))) .collect( Collectors.groupingBy(firp -> firp.getKey().getKey().getKey(), Collectors.groupingBy(firp -> firp.getKey().getKey().getValue() .getStoreId(), Collectors.groupingBy(firp -> firp.getValue().getPaymentDate(), Collectors.summingDouble( firp -> firp.getValue().getAmount().doubleValue() ) ) ) ) ); Use a Seq instead of a Stream
  • 138. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = Seq.seq(loadAllFilms()) .crossApply(f -> f.getInventories()) .crossApply(fi -> fi.v2.getRentals()) .crossApply(fir -> fir.v2.getPayments()) .collect( Collectors.groupingBy(firp -> firp.v1.v1.v1, Collectors.groupingBy(firp -> firp.v1.v1.v2.getStoreId(), Collectors.groupingBy(firp -> firp.v2.getPaymentDate(), Collectors.summingDouble( firp -> firp.v2.getAmount().doubleValue() ) ) ) ) ); Use SQL style CROSS APPLY instead of flatMap()
  • 139. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = Seq.seq(loadAllFilms()) .crossApply(f -> f.getInventories()) // <Film, Inventory> .crossApply(fi -> fi.v2.getRentals()) // <<F, I>, Rental> .crossApply(fir -> fir.v2.getPayments()) // <<<F, I>, R>, Payment> .collect( Collectors.groupingBy(firp -> firp.v1.v1.v1, Collectors.groupingBy(firp -> firp.v1.v1.v2.getStoreId(), Collectors.groupingBy(firp -> firp.v2.getPaymentDate(), Collectors.summingDouble( firp -> firp.v2.getAmount().doubleValue() ) ) ) ) );
  • 140. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = Seq.seq(loadAllFilms()) .crossApply(f -> f.getInventories()) .crossApply(fi -> fi.v2.getRentals()) .crossApply(fir -> fir.v2.getPayments()) .collect( Collectors.groupingBy(firp -> firp.v1.v1.v1, Collectors.groupingBy(firp -> firp.v1.v1.v2.getStoreId(), Collectors.groupingBy(firp -> firp.v2.getPaymentDate(), Collectors.summingDouble( firp -> firp.v2.getAmount().doubleValue() ) ) ) ) ); <<<Film, Inventory>, Rental>, Payment>
  • 141. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = Seq.seq(loadAllFilms()) .crossApply(f -> f.getInventories()) .crossApply(fi -> fi.v2.getRentals().stream() .flatMap(r -> r.getPayments().stream())) .collect( Collectors.groupingBy(fip -> fip.v1.v1, Collectors.groupingBy(fip -> fip.v1.v2.getStoreId(), Collectors.groupingBy(fip -> fip.v2.getPaymentDate(), Collectors.summingDouble( fip -> fip.v2.getAmount().doubleValue() ) ) ) ) ); Hm, never really needed the rentals
  • 142. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Film, Map<Integer, Map<LocalDate, Double>>> result = Seq.seq(loadAllFilms()) .crossApply(f -> f.getInventories()) .crossApply(fi -> fi.v2.getRentals().stream() .flatMap(r -> r.getPayments().stream())) .collect( Collectors.groupingBy(fip -> fip.v1.v1, Collectors.groupingBy(fip -> fip.v1.v2.getStoreId(), Collectors.groupingBy(fip -> fip.v2.getPaymentDate(), Collectors.summingDouble( fip -> fip.v2.getAmount().doubleValue() ) ) ) ) ); A little bit better now...
  • 143. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Tuple3<Film, Integer, LocalDate>, Double> result = Seq.seq(loadAllFilms()) .crossApply(f -> f.getInventories()) .crossApply(fi -> fi.v2.getRentals().stream() .flatMap(r -> r.getPayments().stream())) .groupBy( fip -> tuple( fip.v1.v1, fip.v1.v2.getStoreId(), fip.v2.getPaymentDate() ), Agg.sum(fip -> fip.v2.getAmount()) ); Oh, not that bad, actually ┬─┬ ノ( ゜-゜ノ)
  • 144. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Let’s try that Java algorithm again Map<Tuple3<Film, Integer, LocalDate>, Double> result = Seq.seq(loadAllFilms()) .crossApply(f -> f.getInventories()) .crossApply(fi -> fi.v2.getRentals().stream() .flatMap(r -> r.getPayments().stream())) .groupBy( fip -> tuple( fip.v1.v1, fip.v1.v2.getStoreId(), fip.v2.getPaymentDate() ), Agg.sum(fip -> fip.v2.getAmount()) ); Result type a bit nicer, too
  • 145. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Bad news is: How much time did we spend on this problem now?
  • 146. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Remember this slide? Was it all that hard? SELECT title, store_id, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, store_id, payment_date ORDER BY title, store_id, payment_date
  • 147. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Everyone understands now… SQL is a 4GL This means great improvement of developer productivity
  • 148. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Everyone understands now… How much time did I spend talking about SQL so far? How much time on Java? SQL is easier = SQL is more productive
  • 149. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What will I talk about? • SQL is awesome • SQL is productive • SQL is fast
  • 150. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Suspense! Best chapter: Performance
  • 151. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 But first How does SQL work?
  • 152. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Business asking How many films did each actor whose last name starts with «A» play in?
  • 153. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 They want this Starts with «A» How many films
  • 154. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 This is the query. But what really happens? SELECT first_name, last_name, count(*) FROM actor JOIN film_actor USING (actor_id) WHERE last_name LIKE 'A%' GROUP BY first_name, last_name ORDER BY count(*) DESC
  • 155. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Logical Operations order 1. Load tables
  • 156. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Logical Operations order 1. Load tables Observe: «LOGICAL». Not «ACTUAL»
  • 157. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Logical Operations order 1. Load tables 2. Apply predicates
  • 158. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Logical Operations order 1. Load tables 2. Apply predicates 3. Collect groups
  • 159. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Logical Operations order 1. Load tables 2. Apply predicates 3. Collect groups 4. Aggregate
  • 160. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Logical Operations order 1. Load tables 2. Apply predicates 3. Collect groups 4. Aggregate 5. Project
  • 161. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Logical Operations order 1. Load tables 2. Apply predicates 3. Collect groups 4. Aggregate 5. Project 6. Order
  • 162. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Complete order Logical operations order 1. FROM, JOIN, APPLY 2. WHERE 3. CONNECT BY (Oracle) 4. GROUP BY 5. Aggregations 6. HAVING 7. WINDOW 8. MODEL (Oracle) 9. SELECT 10. DISTINCT 11. UNION, INTERSECT, EXCEPT 12. ORDER BY 13. OFFSET 14. LIMIT 15. FOR UPDATE
  • 163. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What’s the actual algorithm? But that’s not what really happens! Any algorithm that produces the same result is acceptable.
  • 164. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What’s the actual algorithm? Can we see the actual algorithm?
  • 165. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 It’s called «execution plan»
  • 166. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Who has seen an execution plan?
  • 167. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 SQL Developer
  • 168. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 pgAdmin III
  • 169. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 SQL Workbench
  • 170. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 SQL Server Management Studio
  • 171. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What’s the actual algorithm? How many rows from operation
  • 172. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What’s the actual algorithm? How much time does it take
  • 173. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Imperative Actual operations order 1. Access ROWIDs from Index given the predicate What’s the actual algorithm?
  • 174. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What’s the actual algorithm? Imperative Actual operations order 1. Access ROWIDs from Index given the predicate 2. Access other columns from the same row in the table
  • 175. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What’s the actual algorithm? Imperative Actual operations order 1. Access ROWIDs from Index given the predicate 2. Access other columns from the same row in the table 3. Load foreign key relationship index into memory
  • 176. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What’s the actual algorithm? Imperative Actual operations order 1. Access ROWIDs from Index given the predicate 2. Access other columns from the same row in the table 3. Load foreign key relationship index into memory 4. Put both data sets in hashmaps and join them
  • 177. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What’s the actual algorithm? Imperative Actual operations order 1. Access ROWIDs from Index given the predicate 2. Access other columns from the same row in the table 3. Load foreign key relationship index into memory 4. Put both data sets in hashmaps and join them 5. Create another hashmap to group rows
  • 178. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What’s the actual algorithm? Imperative Actual operations order 1. Access ROWIDs from Index given the predicate 2. Access other columns from the same row in the table 3. Load foreign key relationship index into memory 4. Put both data sets in hashmaps and join them 5. Create another hashmap to group rows 6. Sort the result
  • 179. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Huh! Declarative vs Imperative Would you have chosen the same algorithm?
  • 180. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 E.g. Apparently, it’s faster in this case to load 5462 rows into memory than seeking 6 counts individually... Huh!
  • 181. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Big O Notation Hash join: O(N) (N = film_actors (bigger table)) Nested loop join with indexes: O(log M x log N) (M = actors, N = film_actors)
  • 182. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Hash join: O(N) (N = film_actors (bigger table)) Nested loop join with indexes: O(log M x log N) (M = actors, N = film_actors) Big O Notation
  • 183. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Well... It depends!
  • 184. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What you think you have
  • 185. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What you may really have
  • 186. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What you may really have «Works on my machine» ಠ_ಠ
  • 187. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 More info bigocheatsheet.com
  • 188. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Statistics Here’s an interesting thing to think about: Histograms
  • 189. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Statistics Histogram
  • 190. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Statistics Histogram -- Predicate 1 WHERE amount BETWEEN -2000 AND 2000 -- Predicate 2 WHERE amount BETWEEN 5000 AND 9000
  • 191. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Statistics Histogram -- Predicate 1 WHERE amount BETWEEN -2000 AND 2000 -- Predicate 2 WHERE amount BETWEEN 5000 AND 9000 Do both predicates profit from indexing?
  • 192. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Statistics Histogram -- Not very selective predicate WHERE amount BETWEEN -2000 AND 2000 -- Very selective predicate WHERE amount BETWEEN 5000 AND 9000
  • 193. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Statistics Histogram -- Not very selective predicate WHERE amount BETWEEN -2000 AND 2000 -- Very selective predicate WHERE amount BETWEEN 5000 AND 9000
  • 194. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Statistics Accessing the index is only worth the pain if it helps reduce the result set Otherwise, just read from the table
  • 195. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Statistics The database knows all these things. • How many rows are returned from a table? • From a query? • How much does it cost to access the disk? • The cache? • How often is this query run? • How often is the table accessed?
  • 196. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Statistics The database knows all these things. • How much memory do we have? • How many processes are running in parallel right now? • Is the operating system doing anything? • How does the query perform with this bind variable? • Are we running on an HDD or SSD or Flash or RAM? • How many locks do we have on our rows?
  • 197. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Expression trees Everything has a cost
  • 198. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Expression trees How does SQL work? 1. A parsed SQL string produces an expression tree
  • 199. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 How does SQL work? 1. A parsed SQL string produces an expression tree A + (A – B) Expression trees + -A A B
  • 200. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Expression trees How does SQL work? 1. A parsed SQL string produces an expression tree 2. Multiple expression trees are equivalent: They can be transformed into each other
  • 201. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 How does SQL work? 1. A parsed SQL string produces an expression tree 2. Multiple expression trees are equivalent: They can be transformed into each other A + (A – B) Expression trees + -A A B
  • 202. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 How does SQL work? 1. A parsed SQL string produces an expression tree 2. Multiple expression trees are equivalent: They can be transformed into each other A + (A – B) (A + A) - B Expression trees + -A A B + - A A B
  • 203. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 How does SQL work? 1. A parsed SQL string produces an expression tree 2. Multiple expression trees are equivalent: They can be transformed into each other A + (A – B) (2 * A) - B Expression trees + -A A B * - 2 A B
  • 204. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 How does SQL work? 1. A parsed SQL string produces an expression tree 2. Multiple expression trees are equivalent: They can be transformed into each other A + (A – B) (2 * A) - B Expression trees + -A A B * - 2 A B E.g.: Accessing A is super expensive
  • 205. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Expression trees How does SQL work? 1. A parsed SQL string produces an expression tree 2. Multiple expression trees are equivalent: They can be transformed into each other 3. Each expression tree has a corresponding execution plan and an associated, estimated cost 4. The «best» plan (= lowest estimated cost) is chosen 5. The actual execution cost is compared with the estimate to improve future estimates
  • 206. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Expression trees How does SQL work? 1. A parsed SQL string produces an expression tree 2. Multiple expression trees are equivalent: They can be transformed into each other 3. Each expression tree has a corresponding execution plan and an associated, estimated cost 4. The «best» plan (= lowest estimated cost) is chosen 5. The actual execution cost is compared with the estimate to improve future estimates When’s the last time you wrote Java code that did this?
  • 207. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Expression trees Special treat: Oracle 12c can abort and switch execution plans «in flight». This is called «Adaptive Execution Plans».
  • 208. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 What will I talk about? • SQL is awesome • SQL is productive • SQL is fast
  • 209. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Why do I talk about SQL? Now that you know all of this... What do you prefer?
  • 210. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 This? Map<Film, Map<Integer, Map<LocalDate, BigDecimal>>> result = ...; List<Film> films = nPlusOneLoadAllFilms(); // TODO for (Film film : films) { Map<Integer, Map<LocalDate, BigDecimal>> dailyPerStore = result.computeIfAbsent(film, k -> new HashMap<>()); for (Inventory inventory : film.getInventories()) { Map<LocalDate, BigDecimal> daily = dailyPerStore.computeIfAbsent( inventory.getStoreId(), k -> new HashMap()); for (Rental rental : inventory.getRentals()) for (Payment p : rental.getPayments()) daily.compute( p.getPaymentDate(), (k, v) -> v == null ? p.getAmount() : p.getAmount().add(v)); } }
  • 211. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Or, this? SELECT title, store_id, payment_date, SUM(amount) FROM film JOIN inventory USING (film_id) JOIN rental USING (inventory_id) JOIN payment USING (rental_id) GROUP BY film_id, store_id, payment_date ORDER BY title, store_id, payment_date
  • 212. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Why do I talk about SQL? SQL is the only ever successful, mainstream, and general- purpose 4GL (Fourth- Generation Programming Language) And it is awesome!
  • 213. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Why doesn’t anyone else talk about SQL? ¯_(シ)_/¯
  • 214. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Can I write SQL in Java?
  • 215. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Can I write SQL in Java? – Yes. With jOOQ
  • 216. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Can I write SQL in Java? – Yes. With jOOQ
  • 217. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Can I write SQL in Java? – Yes. With jOOQ
  • 218. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 So what’s the key takeaway? 1. Can you do it in the database? Yes 2. Can you do it in the database? Yes (... after visiting my 2 day SQL training) 3. Can you do it in your database? Yes (... unless you're using MySQL) 4. Should you do it in the database? Yes 5. Do long talk titles attract attention? Yes 6. Will this talk ever end? Yes
  • 219. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 If you haven’t had enough Google «10 SQL Tricks» and find the other talk’s transcript https://blog.jooq.org/2016/04/25/10-sql- tricks-that-you-didnt-think-were-possible/
  • 220. Copyright (c) 2009-2017 by Data Geekery GmbH. Slides licensed under CC BY SA 3.0 Thank you Check out our trainings: http://www.jooq.org/training Coordinates • Blog: http://blog.jooq.org (excellent Java SQL content) • Twitter: @JavaOOQ / @lukaseder (more lame jokes) • E-Mail: lukas.eder@datageekery.com • Bank account: CH57 8148 7000 0SQL AWSM 7