Slide 1

Slide 1 text

VISUALIZING POSTGRES 2013-05-24 pgcon ottawa canada 1 2013-05-24 pgcon ottawa canada

Slide 2

Slide 2 text

will @leinweber 2

Slide 3

Slide 3 text

3

Slide 4

Slide 4 text

about the talk 4

Slide 5

Slide 5 text

why visualize 5

Slide 6

Slide 6 text

Anscombe's quartet 6

Slide 7

Slide 7 text

7

Slide 8

Slide 8 text

8

Slide 9

Slide 9 text

crisis 9 respond to page in the middle of the night whatever alert sent page isn't enough to solve the problem, or you would have automated it if you can see at a glance it's faster than grepping through logs => reduce downtime

Slide 10

Slide 10 text

anomalies 10 notice things you haven't seen before things you haven't planned for prompt investigation into odd behavior see the interactions between lots of things

Slide 11

Slide 11 text

capacity planning 11 should I upgrade? are there daily/weekly cycles? => increases robustness

Slide 12

Slide 12 text

remove guessing and gut feelings 12

Slide 13

Slide 13 text

history 13 "let's start with some history "inspiration, lessons, and they're just really neat

Slide 14

Slide 14 text

playfiar william 14 w 1759-1823

Slide 15

Slide 15 text

15 title, frame, labeled axes, labels in the graph, caption, color - in 1786 the line graph and bar chart

Slide 16

Slide 16 text

16

Slide 17

Slide 17 text

17

Slide 18

Slide 18 text

18 - in 1801 the pie chart and circle graph

Slide 19

Slide 19 text

John Snow 19

Slide 20

Slide 20 text

20 - 1854 Broad Street cholera outbreak (soho london) - germ theory was not yet widely accepted

Slide 21

Slide 21 text

21

Slide 22

Slide 22 text

jenny downing http://www.flickr.com/photos/jenny-pics/3761648387/ 22 There was one significant anomaly - none of the monks in the adjacent monastery contracted cholera. Investigation showed that this was not an anomaly, but further evidence, for they drank only beer, which they brewed themselves

Slide 23

Slide 23 text

Charles Joseph Minard 23 w 1781-187 0

Slide 24

Slide 24 text

24 Napoleon graph of 1812 (made in 1869) needs explanation, but has wonderful density

Slide 25

Slide 25 text

25

Slide 26

Slide 26 text

26

Slide 27

Slide 27 text

Edward Tufte 27

Slide 28

Slide 28 text

28

Slide 29

Slide 29 text

data-ink ratio data-ink ratio data-ink ratio data-ink ratio data-ink ratio data-ink ratio data-ink ratio data-ink ratio data-ink ratio 29

Slide 30

Slide 30 text

honesty 30 important not to mislead, even unintentionally (time zone)

Slide 31

Slide 31 text

information consists of differences that make a difference 31

Slide 32

Slide 32 text

sparklines http://tinyurl.com/sparkline 32 small multiples intense data

Slide 33

Slide 33 text

charts 33 get a little more practical

Slide 34

Slide 34 text

line 34

Slide 35

Slide 35 text

35

Slide 36

Slide 36 text

an aside 36 wIJTUPHSBN

Slide 37

Slide 37 text

horizon WJTCFSLFMFZFEVQBQFSTIPSJ[PO 37

Slide 38

Slide 38 text

38

Slide 39

Slide 39 text

http://square.github.io/cubism/ position—small color—large 39 compress vertically without loosing resolution

Slide 40

Slide 40 text

40 small multiples

Slide 41

Slide 41 text

postgres 41

Slide 42

Slide 42 text

pg_stat_statements 42 low level 8.4 Takahiro Itagaki

Slide 43

Slide 43 text

=> select * from pg_stat_statements limit 1; userid | 16384 dbid | 16385 query | SELECT "clip_versions".* FROM "clip_versions" WHERE "clip_versions"."clip_id" = ? ORDER BY created_at desc calls | 103 total_time | 37.603 rows | 632 shared_blks_hit | 504 shared_blks_read | 210 shared_blks_dirtied | 0 shared_blks_written | 0 43

Slide 44

Slide 44 text

select ((total_time::float/calls)::int / 50) * 50 as ms, lpad('', count(*)::int, '') || ' ' || count(*) as freq from pg_stat_statements group by 1 order by 1; \watch 1 44

Slide 45

Slide 45 text

45

Slide 46

Slide 46 text

stat views pg_stat_activity pg_stat_database pg_stat_user_tables pg_stat_user_indexes pg_statio_user_tables pg_statio_user_indexes 46 transactions, rollbacks, bloat, cache hit

Slide 47

Slide 47 text

47

Slide 48

Slide 48 text

pg-extras https://github.com/heroku/heroku-pg-extras cache hit ratio index usage running queries blocked queries locks index size unused indexes sequential scans bloat 48

Slide 49

Slide 49 text

designing a system 49

Slide 50

Slide 50 text

not easy 50 there aren't concrete rules to human perception

Slide 51

Slide 51 text

data is not information 51 just having a metric in graphite or libretto isn't enough -- other people won't have the same context -- you probably need to do conversions such as derivatives

Slide 52

Slide 52 text

too much 52 you get X position Y position and a few colors aspect ratio should make lines 45º if possible

Slide 53

Slide 53 text

53 Cant line up the same time period Minimize Context switching

Slide 54

Slide 54 text

color http://tinyurl.com/colorrules 54 Gray or muted background soft, nature colors for most, bright sparingly for similar categories: single hue, vary saturation different categories: vary hue, but keep saturation

Slide 55

Slide 55 text

intents and needs NF ECB DPOUSBDUPS 55

Slide 56

Slide 56 text

generation 56 Peter Eisentraut => logging yesterday

Slide 57

Slide 57 text

log stream http://www.12factor.net/logs http://boundary.com/blog/2013/05/14/approximate-heavy- hitters-the-spacesaving-algorithm/ http://www.slideshare.net/RedRooz/harmonic-mean-for- monitored-rate-data 57

Slide 58

Slide 58 text

storage http://www.flickr.com/photos/lightmash/3183278318/ 58 storing time series data is a talk in and of itself =>Ronald’s talk yesterday no way i can do it justice as part of this talk rollup, table rotation

Slide 59

Slide 59 text

datascope github.com/will/datascope 59

Slide 60

Slide 60 text

overview 60 pg_stat_statements

Slide 61

Slide 61 text

overview XPSLFSMPPQPCTFSWF SFTFU  TMFFQ TUPSFKTPOQH@TUBU@TUBUFNFOUT  PUIFST DVTUPNDVCJTNEBUBTPVSDF 61

Slide 62

Slide 62 text

schema CREATE TABLE stats ( id serial primary key, created_at timestamptz default (now()), data json); CREATE INDEX ON stats (created_at); 62

Slide 63

Slide 63 text

worker def capture_stats! s = stats DB[:stats] << {data: { connections: connections, stat_statements: stat_statements, cache_hit: cache_hit, locks: locks }.to_json } end 63

Slide 64

Slide 64 text

worker def stat_statements TARGET_DB[:pg_stat_statements] .select(:query, :calls, :total_time) .exclude(query: '') .all end 64

Slide 65

Slide 65 text

thanks @leinweber 65