Postgres is easier

2,281
-1

Published on

A survey of some of the features Postgres has which MySQL doesn't, and which will make your life as a database developer easier

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,281
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
155
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Postgres is easier

    1. 1. Postgres FTW 1: Postgres is just easier
    2. 2. http://www.slideshare.net/gisborne/postgres-is-easier
    3. 3. Data Types• Boolean (!)• Numeric • up to 131072 digits before decimal; 16383 digits after (MySQL: 65 digits)• Network address broadcast(192.168.1.5/24) hostmask(192.168.23.20/30)• UUID• XML• Geometric (point, line, rectangle, circle, path, polygon)• JSON (in 9.2, later in 2012)
    4. 4. Data Types• Make your own! CREATE TYPE inventory_item AS ( ! name text, ! supplier_id integer, ! price numeric); CREATE TABLE on_hand ( ! item inventory_item, ! count integer); INSERT INTO on_hand VALUES (ROW(fuzzy dice, 42, 1.99), 1000); SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9.99;
    5. 5. Custom FunctionsCREATE FUNCTION price_extension(! inventory_item,! integer)RETURNS! numericAS ! SELECT! ! $1.price * $2LANGUAGE SQL;SELECT price_extension(item, 10) FROM on_hand;
    6. 6. Functions! (Statistical)corr(Y, X) regr_sxx(Y, X)covar_pop(Y, X) regr_sxy(Y, X)covar_samp(Y, X) regr_syy(Y, X)regr_avgx(Y, X) stddev(expression)regr_avgy(Y, X) stddev_pop(expression)regr_count(Y, X) stddev_samp(expression)regr_intercept(Y, X) variance(expression)regr_r2(Y, X) var_pop(expression)regr_slope(Y, X) var_samp(expression)
    7. 7. Functions! (Statistical) MySQL:corr(Y, X) regr_sxx(Y, X) MAX()covar_pop(Y, X) regr_sxy(Y, X) MIN()covar_samp(Y, X) regr_syy(Y, X) STD()regr_avgx(Y, X) stddev(expression) STDDEV_POP()regr_avgy(Y, X) stddev_pop(expression) STDDEV_SAMP()regr_count(Y, X) stddev_samp(expression) STDDEV()regr_intercept(Y, X) variance(expression) SUM() VAR_POP()regr_r2(Y, X) var_pop(expression) VAR_SAMP()regr_slope(Y, X) var_samp(expression) VARIANCE()
    8. 8. Functions! (Text Search)• Very fast index updates • Search terms in context (shows how your search• Proximity terms are used in• Weighting scheme context)• Stemming • Regex, substring etc• Stopwords• Modular architecture (add parsers and dictionaries)• Multilingual support
    9. 9. Functions! (Text Search)• Very fast index updates • Search terms in context MySQL: (shows how your search• Proximity terms are used in Regex, substring, etc• Weighting scheme context)• Stemming • Regex, substring etc• Stopwords• Modular architecture (add parsers and dictionaries)• Multilingual support
    10. 10. Functions! (Window Functions)• Aggregate values from single rows• Perform GROUP BY calculations, BUT leave rows intact
    11. 11. Functions! (Window Functions)
    12. 12. Functions! (Window Functions)Any aggregate function: SELECT name, salary, salary / (avg(salary) OVER (PARTITION BY depname)) FROM employee
    13. 13. Functions! (Window Functions)Any aggregate function: SELECT name, salary, salary / (avg(salary) OVER (PARTITION BY depname)) FROM employeeSpecial window functions: SELECT name, rank() OVER (PARTITION BY department_id ORDER BY hire_date ASC) FROM employee
    14. 14. Common Table Expressions• Like a local view; or• Like a named subquery (or named INSERT, DELETE etc)
    15. 15. Common Table ExpressionsSimplify subqueries: WITH SELECT ! regional_sales AS ( ! region, ! ! SELECT ! product, ! ! ! region, ! SUM(quantity) AS product_units, ! ! ! SUM(amount) AS total_sales ! SUM(amount) AS product_sales ! ! FROM FROM ! ! ! orders ! orders ! GROUP BY WHERE ! ! ! region), ! region IN ( ! top_regions AS ( ! ! SELECT ! ! SELECT ! ! ! region ! ! ! region ! ! FROM ! ! FROM ! ! ! top_regions) ! ! ! regional_sales GROUP BY ! ! WHERE ! region, ! ! ! total_sales > ( ! product; ! ! ! ! SELECT ! ! ! ! ! SUM(total_sales)/10 ! ! ! ! FROM ! ! ! ! ! regional_sales))
    16. 16. Common Table ExpressionsRecursive queries: WITH RECURSIVE ! t(n) AS ( ! ! ! VALUES (1) ! ! UNION ALL ! ! ! SELECT ! ! ! ! n+1 ! ! ! FROM ! ! ! ! t ! ! ! WHERE ! ! ! ! n < 100) SELECT ! sum(n) FROM ! t;
    17. 17. Common Table ExpressionsRecursive queries: WITH RECURSIVE ! search_graph(id, link, data, depth) AS ( ! ! ! SELECT ! ! ! ! g.id, ! ! ! ! g.link, ! ! ! ! g.data, ! ! ! ! 1 ! ! ! FROM ! ! ! ! graph g UNION ALL ! ! ! SELECT ! ! ! ! g.id, ! ! ! ! g.link, ! ! ! ! g.data, ! ! ! ! sg.depth + 1 ! ! ! FROM ! ! ! ! graph g, ! ! ! ! search_graph sg ! ! ! WHERE ! ! ! ! g.id = sg.link) SELECT * FROM search_graph;
    18. 18. Common Table ExpressionsRecursive queries: WITH RECURSIVE ! search_graph(id, link, data, depth) AS ( ! ! ! SELECT ! ! ! ! g.id, ! ! ! ! g.link, cl es! ! ! ! ! g.data, cy ! ! ! ! 1 w ith ails ! ! ! FROM ! ! ! ! graph g UNION ALL F ! ! ! SELECT ! ! ! ! g.id, ! ! ! ! g.link, ! ! ! ! g.data, ! ! ! ! sg.depth + 1 ! ! ! FROM ! ! ! ! graph g, ! ! ! ! search_graph sg ! ! ! WHERE ! ! ! ! g.id = sg.link) SELECT * FROM search_graph;
    19. 19. Common Table ExpressionsRecursive queries: WITH RECURSIVE ! ! !SELECT ! search_graph( ! ! !! g.id, ! ! id, ! ! !! g.link, ! ! link, ! ! !! g.data, ! ! data, ! ! !! sg.depth + 1, ! ! depth, ! ! !! path || g.id, ! ! path, ! ! !! g.id = ANY(path) ! ! cycle) AS ( !FROM ! ! ! SELECT ! ! ! ! graph g, ! ! ! ! g.id, ! ! ! ! search_graph sg ! ! ! ! g.link, ! ! ! WHERE ! ! ! ! g.data, ! ! ! ! g.id = sg.link AND ! ! ! ! 1, ! ! ! ! NOT cycle) ! ! ! ! ARRAY[g.id], SELECT * FROM search_graph; ! ! ! ! false ! ! ! FROM ! ! ! ! graph g UNION ALL
    20. 20. Common Table ExpressionsRecursive queries: WITH RECURSIVE ! ! !SELECT ! search_graph( ! ! !! g.id, ! ! id, ! ! !! g.link, ! ! link, ! ! !! g.data, ! ! data, ! ! !! sg.depth + 1, ! ! depth, ! ! !! path || g.id, ! ! path, ! ! !! g.id = ANY(path) ! ! cycle) AS ( !FROM ! ! ! SELECT ! ! ! ! graph g, ! ! ! ! g.id, ! ! ! ! search_graph sg ! ! ! ! g.link, ! ! ! WHERE ! ! ! ! g.data, ! ! ! ! g.id = sg.link AND ! ! ! ! 1, ! ! ! ! NOT cycle) ! ! ! ! ARRAY[g.id], SELECT * FROM search_graph; ! ! ! ! false ! ! ! FROM ! ! ! ! graph g UNION ALL
    21. 21. Common Table ExpressionsRecursive queries: WITH RECURSIVE ! ! !SELECT ! search_graph( ! ! !! g.id, ! ! id, ! ! !! g.link, ! ! link, ! ! !! g.data, ! ! data, ! ! !! sg.depth + 1, ! ! depth, ! ! !! path || g.id, ! ! path, ! ! !! g.id = ANY(path) ! ! cycle) AS ( !FROM ! ! ! SELECT ! ! ! ! graph g, ! ! ! ! g.id, ! ! ! ! search_graph sg ! ! ! ! g.link, ! ! ! WHERE ! ! ! ! g.data, ! ! ! ! g.id = sg.link AND ! ! ! ! 1, ! ! ! ! NOT cycle) ! ! ! ! ARRAY[g.id], SELECT * FROM search_graph; ! ! ! ! false ! ! ! FROM ! ! ! ! graph g UNION ALL
    22. 22. Common Table ExpressionsRecursive queries: WITH RECURSIVE ! ! !SELECT ! search_graph( ! ! !! g.id, ! ! id, ! ! !! g.link, ! ! link, ! ! !! g.data, ! ! data, ! ! !! sg.depth + 1, ! ! depth, ! ! !! path || g.id, ! ! path, ! ! !! g.id = ANY(path) ! ! cycle) AS ( !FROM ! ! ! SELECT ! ! ! ! graph g, ! ! ! ! g.id, ! ! ! ! search_graph sg ! ! ! ! g.link, ! ! ! WHERE ! ! ! ! g.data, ! ! ! ! g.id = sg.link AND ! ! ! ! 1, ! ! ! ! NOT cycle) ! ! ! ! ARRAY[g.id], SELECT * FROM search_graph; ! ! ! ! false ! ! ! FROM ! ! ! ! graph g UNION ALL
    23. 23. Common Table ExpressionsModifying data: WITH ! moved_rows AS ( ! ! DELETE ! ! FROM ! ! ! products ! ! WHERE ! ! ! "date" >= 2010-10-01 AND ! ! ! "date" < 2010-11-01 ! RETURNING *) INSERT INTO ! products_log SELECT ! * FROM ! moved_rows;
    24. 24. Small but big features
    25. 25. Small but big features• Index in the background
    26. 26. Small but big features• Index in the background• Transactional schema changes
    27. 27. Small but big features• Index in the background• Transactional schema changes• Fast schema changes
    28. 28. Small but big features• Index in the background• Transactional schema changes• Fast schema changes • Drop column instantly
    29. 29. Small but big features• Index in the background• Transactional schema changes• Fast schema changes • Drop column instantly • Add column instantly (unless default value)
    30. 30. NoSQL?
    31. 31. NoSQL in your SQL (Arrays)• Array type CREATE TABLE sal_emp ( INSERT INTO ! name text, ! sal_emp ! pay_by_quarter integer[], VALUES ( ! schedule text[][]); ! Carol, ! {20000, 25000, 25000, 25000}, INSERT INTO ! { ! sal_emp ! ! {"breakfast", "consulting"}, VALUES ( ! ! {"meeting", "lunch"} ! Bill, ! }); ! {10000, 10000, 10000, 10000}, ! { ! ! {"meeting", "lunch"}, ! ! {"training", "presentation"} ! });
    32. 32. NoSQL in your SQL (Arrays)SELECT * FROM sal_emp; name | pay_by_quarter | schedule-------+---------------------------+------------------------------------------- Bill | {10000,10000,10000,10000} | {{meeting,lunch},{training,presentation}} Carol | {20000,25000,25000,25000} | {{breakfast,consulting},{meeting,lunch}}(2 rows)SELECT name FROM sal_emp WHERE pay_by_quarter[1] <> pay_by_quarter[2]; name------- Carol(1 row)
    33. 33. NoSQL in your SQL (Arrays)SELECT schedule[1:2][1:1] FROM sal_emp WHERE name = Bill; schedule------------------------ {{meeting},{training}}(1 row)SELECT * FROM sal_emp WHERE 10000 = ANY (pay_by_quarter);ARRAY[1,4,3] @> ARRAY[3,1]
    34. 34. NoSQL in your SQL (Arrays)SELECT! buyer,! SUM(total),! ARRAY_AGG(order_date ORDER BY total DESC)FROM! ordersGROUP BY! buyer;buyer | sum | array_agg------+------+-------------------------------------------------------------------Alice | 1057 | {2009-05-08,2009-08-15,2009-03-25,2009-08-16}Bob | 905 | {2009-02-10,2009-01-29,2009-08-17,2009-05-12,2009-08-22,2009-05-28}Carol | 1118 | {2009-04-28,2009-09-01,2009-03-30,2009-06-27-01-10,2009-09-06}Dave | 1239 | {2009-05-28,2009-07-27,2009-02-07,2009-07-15,2009-08-27}Eve | 1222 | {2009-02-01,2009-08-14,2009-09-26,2009-04-07-10-02}(5 rows)
    35. 35. NoSQL in your SQL (HStore)Key-value store:create_table :products do |t|! t.string :name! t.hstore :data! t.timestampsendgem install activerecord-postgres-hstoreProduct.create(! name: "Geek Love: A Novel", data: {author => Katherine Dunn, pages => 368, category => fiction})Product.last.data[category] # => fiction
    36. 36. NoSQL in your SQL (HStore)# Find all products that have a key of author in dataProduct.where("data ? :key", :key => author)# Find all products that have a pages and 368 key value pair in dataProduct.where("data @> (:key => :value)", :key => pages, :value => 368)# Find all products that dont have a key value pair pages and 999 in dataProduct.where("not data @> (:key => :value)", :key => pages, :value => 999)# Find all products having key author and value like ba in dataProduct.where("data -> :key LIKE :value", :key => author, :value => "%Kat%")
    37. 37. Use a really good languageCREATE FUNCTION tu(varchar)RETURNS setof recordAS ! size = PL.column_name(args[0]).size! res = nil! PL::Plan.new("select * from #{args[0]}", block => 50).each do |row|! ! if res.nil?! ! ! res = row.values! ! else! ! ! res.concat row.values! ! ! yield res! ! ! res = nil! ! end! end! if res! ! res.concat Array.new(size)! ! yield res! end language plruby;CREATE FUNCTION
    38. 38. FINhttp://www.slideshare.net/gisborne/postgres-is-easier guyren@relevantlogic.com http://relevantlogic.com

    ×