Нетрадиционное
                  использование Ruby и
                       PostgreSQL
                            Иван Евтухович




вторник, 18 декабря 12 г.
вторник, 18 декабря 12 г.
вторник, 18 декабря 12 г.
вторник, 18 декабря 12 г.
О чем этот доклад?


                    • О смерти Ruby?
                    • О чем-то, что будет полезно?


вторник, 18 декабря 12 г.
• ruby внутри vim
                    • ruby и PostgreSQL (полезная часть)
                    • ruby и PostgreSQL (бесполезная часть)


вторник, 18 декабря 12 г.
Ruby и Vim

                    • :help ruby
                    • 200 строк документации
                    • пару десятков функций


вторник, 18 декабря 12 г.
$ pwd
         /Users/brun/Projects/vim/src
        $ wc if_ruby.c
           1346 3621 35552 if_ruby.c



вторник, 18 декабря 12 г.
Этого достаточно


                    • волшебные методы Vim.command и
                            Vim.evaluate




вторник, 18 декабря 12 г.
Vim.command
                    • выполняет любую команду командного
                            режима Vim


             :ruby Vim.command(‘help ruby’)
             :help ruby

вторник, 18 декабря 12 г.
Vim.evaluate

                    • вычисляет любое выражение в vim

         :ruby puts Vim.evaluate(‘2012’).class
         Fixnum



вторник, 18 декабря 12 г.
Проблемы

                    • нет eval, но есть pyeval() :-(
                    • я не нашел хороших примеров
                            использования
                    • VimL


вторник, 18 декабря 12 г.
вторник, 18 декабря 12 г.
function! Serpinski()
     ruby << EOF
     def draw(arr, x, y)
       arr[x][y] = '*'
     end

     def carpet(arr, size, x, y)
       if size == 1
         draw(arr, x, y)
       else
         new_size = size / 3
         carpet(arr, new_size, x, y)
         carpet(arr, new_size, x + new_size, y)
         carpet(arr, new_size, x + new_size * 2,   y)
         carpet(arr, new_size, x, y + new_size)
         carpet(arr, new_size, x + new_size * 2,   y + new_size)
         carpet(arr, new_size, x, y + new_size *   2)
         carpet(arr, new_size, x + new_size, y +   new_size * 2)
         carpet(arr, new_size, x + new_size * 2,   y + new_size * 2)
       end
     end

     arr = Array.new(27) { Array.new }
     carpet(arr, 27, 0, 0)

     arr.each_with_index do |line, i|
       l = line.map { |e| e.nil? ? ' ' : e }
       Vim::Buffer.current.append(Vim::Buffer.current.line_number + i, l.join(''))
     end
     EOF
     endfunction


вторник, 18 декабря 12 г.
• :call Serpinski()
                    • :nmap <F7> :call Serpinski() <CR>



вторник, 18 декабря 12 г.
HSTORE

                    • расширение в PostgreSQL
                    • хранить ключ-значение
                    • нет вложенности
                    • ключ и значение — строки
                    • CREATE EXTENSION hstore

вторник, 18 декабря 12 г.
CREATE table test(id serial, value hstore);

 “ заполним таблицу тестовыми данными

 CREATE INDEX ON test USING GIN(value);


 EXPLAIN SELECT value -> '111' FROM test WHERE value ? '111';
                                   QUERY PLAN
 ------------------------------------------------------------------------------
  Bitmap Heap Scan on test (cost=12.01..16.02 rows=1 width=114)
    Recheck Cond: (value ? '111'::text)
    -> Bitmap Index Scan on test_value_idx (cost=0.00..12.01 rows=1 width=0)
          Index Cond: (value ? '111'::text)




вторник, 18 декабря 12 г.
serialize
                    • http://apidock.com/rails/ActiveRecord/Base/
                            serialize/class


                class User < ActiveRecord::Base
                  serialize :preferences
                end



вторник, 18 декабря 12 г.
Спецсредства
  https://github.com/engageis/activerecord-postgres-hstore


 rails	
  g	
  model	
  User	
  email:string	
  value:hstore

 User.where("value ? 'name'")

 User.where("value @> 'name=>Ivan'")

 SELECT "users".* FROM "users" WHERE (value
 @> 'name=>Ivan')

вторник, 18 декабря 12 г.
explain SELECT "users".* FROM "users"
     WHERE (value @> 'name=>Ivan');

                    QUERY PLAN
     ------------------------------------------
     Index Scan using test_value_idx on users
           (cost=0.00..8.27 rows=1 width=182)
        Index Cond: (value @> '"name"=>"Ivan"'::hstore)




вторник, 18 декабря 12 г.
Arrays
                    • В PostgreSQL есть массивы однотипных
                            элементов
                    • Поддержка массивов pg появилась в
                            rails 4
                    • Есть бэкпорт в rails 3
                    • https://github.com/tlconnor/activerecord-
                            postgres-array


вторник, 18 декабря 12 г.
class CreateBooks <
  ActiveRecord::Migration
    def change
      create_table :books do |t|
        t.text :name
        t.text_array :authors
        t.timestamps
      end
    end
  end
вторник, 18 декабря 12 г.
create index on books using
  gin(authors);

  Book.create! :authors => ["Ivan
  Evtukhovich", "Ivan Samsonov"]

  Book.where("authors @> ARRAY['Ivan
  Samsonov']")



вторник, 18 декабря 12 г.
explain select * from books where
authors @> ARRAY['Ivan Samsonov'];

QUERY PLAN
----------------------------------
 Bitmap Heap Scan on books
(cost=8.03..16.49 rows=4 width=84)
   Recheck Cond: (authors @> '{"Ivan
Samsonov"}'::text[])
   -> Bitmap Index Scan on
books_authors_idx (cost=0.00..8.03
rows=4 width=0)
         Index Cond: (authors @> '{"Ivan
Samsonov"}'::text[])
вторник, 18 декабря 12 г.
Хипстерское
                             хранилище
                    • документоориентированное
                    • schemaless
                    • быстрый поиск
                    • быстрая запись
                    • без join-ов
                    • web scale
вторник, 18 декабря 12 г.
Имя?

                    • rake
                    • rdebug
                    • rmagick
                    • rdoc

вторник, 18 декабря 12 г.
Имя?

                    • cruisecontrol.rb
                    • perftools.rb
                    • gdb.rb


вторник, 18 декабря 12 г.
r_____.rb


вторник, 18 декабря 12 г.
rmongo.rb

вторник, 18 декабря 12 г.
Прообраз

                    • http://docs.mongodb.org/manual/tutorial/
                            getting-started/
                    • early pre alfa version
                    • продукт не будет развиваться


вторник, 18 декабря 12 г.
вторник, 18 декабря 12 г.
Реализовано

                    • find
                    • insert
                    • count
                    • ensureIndex

вторник, 18 декабря 12 г.
Live
           Demo
вторник, 18 декабря 12 г.
Формат документа?



вторник, 18 декабря 12 г.
YAML



вторник, 18 декабря 12 г.
Как и обещал
                    • документоориентированное √
                    • schemaless √
                    • быстрый поиск √
                    • быстрая запись √
                    • без join-ов √
                    • web scale √
вторник, 18 декабря 12 г.
Что внутри?



вторник, 18 декабря 12 г.
pl/ruby
                    • https://github.com/globegit/postgresql-
                            plruby
                    • хрен поставишь
                    • только ruby 1.8.x
                    • не завелся на PostgreSQL 9.2
                    • добровольцы?
вторник, 18 декабря 12 г.
Table "public.things"

                Column | Type    |
               --------+---------+
                id     | integer |
                value | text     |




вторник, 18 декабря 12 г.
• Со вставкой все понятно
                    • А с поиском?



вторник, 18 декабря 12 г.
db.things.find("title" => "Книга")

      SELECT * FROM things WHERE
        rmongorb_get_key('title'::text, value) = 'Книга'

      CREATE OR REPLACE FUNCTION
       rmongorb_get_key(key text, value text)
       RETURNS text AS '
        require "yaml"
        obj = YAML.load(value)
        obj[key]
      ' LANGUAGE 'plruby' IMMUTABLE;




вторник, 18 декабря 12 г.
Быстрый поиск


                    • функциональные индексы в PostgreSQL
                    • http://www.postgresql.org/docs/9.2/static/
                            indexes-expressional.html




вторник, 18 декабря 12 г.
db.things.ensureIndex(
      {"last_name" => 1})

    CREATE INDEX ON things
    (rmongorb_get_key(
      'last_name'::text, value))




вторник, 18 декабря 12 г.
EXPLAIN SELECT * FROM things WHERE
 rmongorb_get_key('last_name'::text, value) =
   'Сидоров' ;

 QUERY PLAN
 -------------------------------------
  Index Scan using
       things_rmongorb_get_key_idx2 on things
       (cost=0.25..20.53 rows=4 width=222)
    Index Cond:
      (rmongorb_get_key('last_name'::text,
 value) = 'Сидоров'::text)




вторник, 18 декабря 12 г.
Быстрая запись


                    • synchronous_commit = on
                    • http://www.postgresql.org/docs/9.2/static/
                            wal-async-commit.html




вторник, 18 декабря 12 г.
Что еще можно
                               сделать?
                    • вложенные ключи
                    • join на самом деле есть :-)
                    • sharding
                    • http://ssql-railsconf.herokuapp.com/

вторник, 18 декабря 12 г.
Спасибо!

                                 @rubynoname
                                  @evtuhovich
                            evtuhovich@gmail.com
                            http://blog.evtuhovich.ru/




вторник, 18 декабря 12 г.

Нетрадиционное использование Ruby и PostgreSQL

  • 1.
    Нетрадиционное использование Ruby и PostgreSQL Иван Евтухович вторник, 18 декабря 12 г.
  • 2.
  • 3.
  • 4.
  • 5.
    О чем этотдоклад? • О смерти Ruby? • О чем-то, что будет полезно? вторник, 18 декабря 12 г.
  • 6.
    • ruby внутриvim • ruby и PostgreSQL (полезная часть) • ruby и PostgreSQL (бесполезная часть) вторник, 18 декабря 12 г.
  • 7.
    Ruby и Vim • :help ruby • 200 строк документации • пару десятков функций вторник, 18 декабря 12 г.
  • 8.
    $ pwd /Users/brun/Projects/vim/src $ wc if_ruby.c 1346 3621 35552 if_ruby.c вторник, 18 декабря 12 г.
  • 9.
    Этого достаточно • волшебные методы Vim.command и Vim.evaluate вторник, 18 декабря 12 г.
  • 10.
    Vim.command • выполняет любую команду командного режима Vim :ruby Vim.command(‘help ruby’) :help ruby вторник, 18 декабря 12 г.
  • 11.
    Vim.evaluate • вычисляет любое выражение в vim :ruby puts Vim.evaluate(‘2012’).class Fixnum вторник, 18 декабря 12 г.
  • 12.
    Проблемы • нет eval, но есть pyeval() :-( • я не нашел хороших примеров использования • VimL вторник, 18 декабря 12 г.
  • 13.
  • 14.
    function! Serpinski() ruby << EOF def draw(arr, x, y) arr[x][y] = '*' end def carpet(arr, size, x, y) if size == 1 draw(arr, x, y) else new_size = size / 3 carpet(arr, new_size, x, y) carpet(arr, new_size, x + new_size, y) carpet(arr, new_size, x + new_size * 2, y) carpet(arr, new_size, x, y + new_size) carpet(arr, new_size, x + new_size * 2, y + new_size) carpet(arr, new_size, x, y + new_size * 2) carpet(arr, new_size, x + new_size, y + new_size * 2) carpet(arr, new_size, x + new_size * 2, y + new_size * 2) end end arr = Array.new(27) { Array.new } carpet(arr, 27, 0, 0) arr.each_with_index do |line, i| l = line.map { |e| e.nil? ? ' ' : e } Vim::Buffer.current.append(Vim::Buffer.current.line_number + i, l.join('')) end EOF endfunction вторник, 18 декабря 12 г.
  • 15.
    • :call Serpinski() • :nmap <F7> :call Serpinski() <CR> вторник, 18 декабря 12 г.
  • 16.
    HSTORE • расширение в PostgreSQL • хранить ключ-значение • нет вложенности • ключ и значение — строки • CREATE EXTENSION hstore вторник, 18 декабря 12 г.
  • 17.
    CREATE table test(idserial, value hstore); “ заполним таблицу тестовыми данными CREATE INDEX ON test USING GIN(value); EXPLAIN SELECT value -> '111' FROM test WHERE value ? '111'; QUERY PLAN ------------------------------------------------------------------------------ Bitmap Heap Scan on test (cost=12.01..16.02 rows=1 width=114) Recheck Cond: (value ? '111'::text) -> Bitmap Index Scan on test_value_idx (cost=0.00..12.01 rows=1 width=0) Index Cond: (value ? '111'::text) вторник, 18 декабря 12 г.
  • 18.
    serialize • http://apidock.com/rails/ActiveRecord/Base/ serialize/class class User < ActiveRecord::Base serialize :preferences end вторник, 18 декабря 12 г.
  • 19.
    Спецсредства https://github.com/engageis/activerecord-postgres-hstore rails  g  model  User  email:string  value:hstore User.where("value ? 'name'") User.where("value @> 'name=>Ivan'") SELECT "users".* FROM "users" WHERE (value @> 'name=>Ivan') вторник, 18 декабря 12 г.
  • 20.
    explain SELECT "users".*FROM "users" WHERE (value @> 'name=>Ivan'); QUERY PLAN ------------------------------------------ Index Scan using test_value_idx on users (cost=0.00..8.27 rows=1 width=182) Index Cond: (value @> '"name"=>"Ivan"'::hstore) вторник, 18 декабря 12 г.
  • 21.
    Arrays • В PostgreSQL есть массивы однотипных элементов • Поддержка массивов pg появилась в rails 4 • Есть бэкпорт в rails 3 • https://github.com/tlconnor/activerecord- postgres-array вторник, 18 декабря 12 г.
  • 22.
    class CreateBooks < ActiveRecord::Migration def change create_table :books do |t| t.text :name t.text_array :authors t.timestamps end end end вторник, 18 декабря 12 г.
  • 23.
    create index onbooks using gin(authors); Book.create! :authors => ["Ivan Evtukhovich", "Ivan Samsonov"] Book.where("authors @> ARRAY['Ivan Samsonov']") вторник, 18 декабря 12 г.
  • 24.
    explain select *from books where authors @> ARRAY['Ivan Samsonov']; QUERY PLAN ---------------------------------- Bitmap Heap Scan on books (cost=8.03..16.49 rows=4 width=84) Recheck Cond: (authors @> '{"Ivan Samsonov"}'::text[]) -> Bitmap Index Scan on books_authors_idx (cost=0.00..8.03 rows=4 width=0) Index Cond: (authors @> '{"Ivan Samsonov"}'::text[]) вторник, 18 декабря 12 г.
  • 25.
    Хипстерское хранилище • документоориентированное • schemaless • быстрый поиск • быстрая запись • без join-ов • web scale вторник, 18 декабря 12 г.
  • 26.
    Имя? • rake • rdebug • rmagick • rdoc вторник, 18 декабря 12 г.
  • 27.
    Имя? • cruisecontrol.rb • perftools.rb • gdb.rb вторник, 18 декабря 12 г.
  • 28.
  • 29.
  • 30.
    Прообраз • http://docs.mongodb.org/manual/tutorial/ getting-started/ • early pre alfa version • продукт не будет развиваться вторник, 18 декабря 12 г.
  • 31.
  • 32.
    Реализовано • find • insert • count • ensureIndex вторник, 18 декабря 12 г.
  • 33.
    Live Demo вторник, 18 декабря 12 г.
  • 34.
  • 35.
  • 36.
    Как и обещал • документоориентированное √ • schemaless √ • быстрый поиск √ • быстрая запись √ • без join-ов √ • web scale √ вторник, 18 декабря 12 г.
  • 37.
  • 38.
    pl/ruby • https://github.com/globegit/postgresql- plruby • хрен поставишь • только ruby 1.8.x • не завелся на PostgreSQL 9.2 • добровольцы? вторник, 18 декабря 12 г.
  • 39.
    Table "public.things" Column | Type | --------+---------+ id | integer | value | text | вторник, 18 декабря 12 г.
  • 40.
    • Со вставкойвсе понятно • А с поиском? вторник, 18 декабря 12 г.
  • 41.
    db.things.find("title" => "Книга") SELECT * FROM things WHERE rmongorb_get_key('title'::text, value) = 'Книга' CREATE OR REPLACE FUNCTION rmongorb_get_key(key text, value text) RETURNS text AS ' require "yaml" obj = YAML.load(value) obj[key] ' LANGUAGE 'plruby' IMMUTABLE; вторник, 18 декабря 12 г.
  • 42.
    Быстрый поиск • функциональные индексы в PostgreSQL • http://www.postgresql.org/docs/9.2/static/ indexes-expressional.html вторник, 18 декабря 12 г.
  • 43.
    db.things.ensureIndex( {"last_name" => 1}) CREATE INDEX ON things (rmongorb_get_key( 'last_name'::text, value)) вторник, 18 декабря 12 г.
  • 44.
    EXPLAIN SELECT *FROM things WHERE rmongorb_get_key('last_name'::text, value) = 'Сидоров' ; QUERY PLAN ------------------------------------- Index Scan using things_rmongorb_get_key_idx2 on things (cost=0.25..20.53 rows=4 width=222) Index Cond: (rmongorb_get_key('last_name'::text, value) = 'Сидоров'::text) вторник, 18 декабря 12 г.
  • 45.
    Быстрая запись • synchronous_commit = on • http://www.postgresql.org/docs/9.2/static/ wal-async-commit.html вторник, 18 декабря 12 г.
  • 46.
    Что еще можно сделать? • вложенные ключи • join на самом деле есть :-) • sharding • http://ssql-railsconf.herokuapp.com/ вторник, 18 декабря 12 г.
  • 47.
    Спасибо! @rubynoname @evtuhovich evtuhovich@gmail.com http://blog.evtuhovich.ru/ вторник, 18 декабря 12 г.