sequel_pg

repository·master·Indexed 42 days ago

https://github.com/jeremyevans/sequel_pg

A high-performance C extension for the Sequel postgres adapter that replaces the pure Ruby row-fetching loop with a C implementation. It optimizes Sequel::Model instance creation, dataset iteration, and specific Dataset methods such as map, as_hash, and to_hash_groups. Additionally, it provides the :pg_streaming extension for processing large result sets one row at a time.

Tokens
2.3K
Snippets
9
Records
15
Agent score
54%

What's inside sequel_pg

  1. Speed up Sequel dataset methods with sequel_pg

    master

    By overwriting the inner loop of the Sequel postgres adapter with a C version, sequel_pg significantly improves performance for row fetching and several Dataset methods, including:

    • map
    • as_hash/to_hash
    • to_hash_groups
    • select_hash
    • select_hash_groups
    • select_map
    • select_order_map

    It also optimizes model instance creation when loading model datasets.

  2. Install the sequel_pg gem

    master

    Install the gem using the standard gem command. To ensure the installation succeeds, the pg_config binary must be in your PATH so the installer can locate the PostgreSQL shared library and header files.

    Alternatively, you can specify the locations manually using the POSTGRES_LIB and POSTGRES_INCLUDE environment variables.

    gem install sequel_pg
  3. Configure sequel_pg in a Gemfile

    master

    Because the sequel postgres adapter automatically requires sequel_pg if it is available, you should use the require: 'sequel' option in your Gemfile to prevent redundant or incorrect loading.

    gem 'sequel_pg', require: 'sequel'
  4. Use streaming to process large result sets

    master

    If you are using PostgreSQL 9.2+ on the client, sequel_pg enables streaming support. This allows you to process rows one at a time instead of loading the entire result set into memory.

    1. Check if streaming is supported: Sequel::Postgres.supports_streaming?

    2. Load the streaming extension into your database connection: DB.extension(:pg_streaming)

    3. Use the Dataset#stream method to iterate over rows: DB[:table].stream.each { |row| ... }

    To enable streaming for all datasets on a database connection, set DB.stream_all_queries = true.

    # Check support
    Sequel::Postgres.supports_streaming?
    
    # Enable for a specific database connection
    DB.extension(:pg_streaming)
    DB[:table].stream.each { |row| puts row }
    
    # Enable for all queries on this connection
    DB.stream_all_queries = true
  5. Understand streaming constraints and streamable queries

    master

    Not all queries can be streamed. The :pg_streaming extension determines if a query is streamable? based on the following rules:

    • Streamable: Most standard queries.
    • Not Streamable:
      • Queries using cursors (:cursor option is present).
      • Queries using specific optimizations like map, select_map, to_hash, or to_hash_groups (detected via _sequel_pg_type).

    Streaming is only triggered if stream_results? is true, which requires either the :stream option to be explicitly set on the dataset or DB.stream_all_queries to be true.

  6. Optimize Sequel Model loading with sequel_pg

    master

    The sequel_pg extension provides optimizations for Sequel::Model instance creation and dataset iteration. When using a Sequel::Postgres::Dataset, the each method is automatically intercepted to use an optimized path if certain conditions are met.

    To trigger the optimized model load, the following conditions must be satisfied:

    1. The row_proc must be a Sequel::Model class.
    2. The row_proc must not be a 'graphed' dataset (it must not use eager_graph or similar).
    3. The dataset must not be using a cursor.
    4. The row_proc must not have shape_friendly set to true (if Sequel::Model.respond_to?(:shape_friendly) is available).
    5. The row_proc's call method must be owned by Sequel::Model::ClassMethods.
    6. The dataset option :optimize_model_load must not be explicitly set to false.

    If these conditions are met, each will use fetch_rows with internal flags (:_sequel_pg_type=>:model) to bypass standard row processing in favor of the optimized version.

  7. Enable PostgreSQL streaming support

    master

    To fetch rows one at a time from PostgreSQL using sequel_pg, load the :pg_streaming extension into your database object.

    Note: This extension modifies connections. You must call DB.disconnect after loading the extension so that new connections are initialized with the necessary streaming methods.

    Requirements:

    • sequel_pg must be loaded.
    • The version of libpq in use must support streaming.
    DB.extension(:pg_streaming)
    # Required to ensure new connections get the streaming methods
    DB.disconnect
  8. Troubleshoot date/timestamp handling

    master

    You must use the ISO PostgreSQL date format. Using SQL, POSTGRESQL, or GERMAN date formats will result in incorrect date/timestamp handling.

    Sequel and PostgreSQL both default to ISO, but if you have explicitly disabled it using DB.use_iso_date_format = false, you may encounter issues.

  9. Troubleshoot installation on systems with --no-undefined

    master
    If RbConfig::CONFIG['LDFLAGS'] contains -Wl,--no-undefined, you may encounter issues installing sequel_pg on certain Unix-like operating systems. This is because sequel_pg calls functions defined in the pg gem, which may not be visible under these strict linking rules.
  10. Troubleshoot pg gem platform issues

    master

    Using a precompiled pg gem can cause issues because it might statically link a libpq version that differs from the system libpq dynamically linked to sequel_pg.

    To resolve this, force the pg gem to use the Ruby platform.

    # In your Gemfile
    gem 'pg', force_ruby_platform: true
    
    # Or via manual install
    gem install pg --platform ruby
  11. Manage optimized model loading in Sequel::Postgres::Dataset

    master

    Optimized model loading is enabled by default in sequel_pg. While Sequel::Postgres::Database#optimize_model_load is deprecated and always returns true, you can control optimization on a per-dataset basis using Sequel::Postgres::Dataset#with_optimize_model_load.

    Note that the mutation method Dataset#optimize_model_load= is deprecated. Use with_optimize_model_load to return a modified copy of the dataset with the setting changed.

    # Instead of mutating the dataset:
    # dataset.optimize_model_load = false (DEPRECATED)
    
    # Use with_optimize_model_load to get a new dataset instance:
    dataset = dataset.with_optimize_model_load(false)