Commit d24ee2a2 authored by Yorick Peterse's avatar Yorick Peterse Committed by Robert Speicher
Browse files

Added trigram indexes for various searched columns

This allows the LIKE condition to use an index. Without a GIN + trigram
index LIKE queries using a wildcard at the start _won't_ use an index
and instead perform a sequence scan.
parent ee14ac68
Loading
Loading
Loading
Loading
+50 −0
Changes for db/migrate/20160226114608_add_trigram_indexes_for_searching.rb: 50 added lines, 0 removed lines.
Original line number Diff line number Diff line
class AddTrigramIndexesForSearching < ActiveRecord::Migration
  disable_ddl_transaction!

  def up
    return unless Gitlab::Database.postgresql?

    unless trigrams_enabled?
      raise 'You must enable the pg_trgm extension as a PostgreSQL super user'
    end

    # trigram indexes are case-insensitive so we can just index the column
    # instead of indexing lower(column)
    to_index.each do |table, columns|
      columns.each do |column|
        execute "CREATE INDEX CONCURRENTLY index_#{table}_on_#{column}_trigram ON #{table} USING gin(#{column} gin_trgm_ops);"
      end
    end
  end

  def down
    return unless Gitlab::Database.postgresql?

    to_index.each do |table, columns|
      columns.each do |column|
        remove_index table, name: "index_#{table}_on_#{column}_trigram"
      end
    end
  end

  def trigrams_enabled?
    res = execute("SELECT true AS enabled FROM pg_available_extensions WHERE name = 'pg_trgm' AND installed_version IS NOT NULL;")
    row = res.first

    row && row['enabled'] == 't' ? true : false
  end

  def to_index
    {
      ci_runners:     [:token, :description],
      issues:         [:title, :description],
      merge_requests: [:title, :description],
      milestones:     [:title, :description],
      namespaces:     [:name, :path],
      notes:          [:note],
      projects:       [:name, :path, :description],
      snippets:       [:title, :file_name],
      users:          [:username, :name, :email]
    }
  end
end
+21 −0
Changes for db/schema.rb: 21 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"
  enable_extension "pg_trgm"

  create_table "abuse_reports", force: :cascade do |t|
    t.integer  "reporter_id"
@@ -258,6 +259,9 @@
    t.string   "architecture"
  end

  add_index "ci_runners", ["description"], name: "index_ci_runners_on_description_trigram", using: :gin
  add_index "ci_runners", ["token"], name: "index_ci_runners_on_token_trigram", using: :gin

  create_table "ci_services", force: :cascade do |t|
    t.string   "type"
    t.string   "title"
@@ -417,11 +421,13 @@
  add_index "issues", ["author_id"], name: "index_issues_on_author_id", using: :btree
  add_index "issues", ["created_at", "id"], name: "index_issues_on_created_at_and_id", using: :btree
  add_index "issues", ["created_at"], name: "index_issues_on_created_at", using: :btree
  add_index "issues", ["description"], name: "index_issues_on_description_trigram", using: :gin
  add_index "issues", ["milestone_id"], name: "index_issues_on_milestone_id", using: :btree
  add_index "issues", ["project_id", "iid"], name: "index_issues_on_project_id_and_iid", unique: true, using: :btree
  add_index "issues", ["project_id"], name: "index_issues_on_project_id", using: :btree
  add_index "issues", ["state"], name: "index_issues_on_state", using: :btree
  add_index "issues", ["title"], name: "index_issues_on_title", using: :btree
  add_index "issues", ["title"], name: "index_issues_on_title_trigram", using: :gin

  create_table "keys", force: :cascade do |t|
    t.integer  "user_id"
@@ -543,12 +549,14 @@
  add_index "merge_requests", ["author_id"], name: "index_merge_requests_on_author_id", using: :btree
  add_index "merge_requests", ["created_at", "id"], name: "index_merge_requests_on_created_at_and_id", using: :btree
  add_index "merge_requests", ["created_at"], name: "index_merge_requests_on_created_at", using: :btree
  add_index "merge_requests", ["description"], name: "index_merge_requests_on_description_trigram", using: :gin
  add_index "merge_requests", ["milestone_id"], name: "index_merge_requests_on_milestone_id", using: :btree
  add_index "merge_requests", ["source_branch"], name: "index_merge_requests_on_source_branch", using: :btree
  add_index "merge_requests", ["source_project_id"], name: "index_merge_requests_on_source_project_id", using: :btree
  add_index "merge_requests", ["target_branch"], name: "index_merge_requests_on_target_branch", using: :btree
  add_index "merge_requests", ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid", unique: true, using: :btree
  add_index "merge_requests", ["title"], name: "index_merge_requests_on_title", using: :btree
  add_index "merge_requests", ["title"], name: "index_merge_requests_on_title_trigram", using: :gin

  create_table "milestones", force: :cascade do |t|
    t.string   "title",       null: false
@@ -562,10 +570,12 @@
  end

  add_index "milestones", ["created_at", "id"], name: "index_milestones_on_created_at_and_id", using: :btree
  add_index "milestones", ["description"], name: "index_milestones_on_description_trigram", using: :gin
  add_index "milestones", ["due_date"], name: "index_milestones_on_due_date", using: :btree
  add_index "milestones", ["project_id", "iid"], name: "index_milestones_on_project_id_and_iid", unique: true, using: :btree
  add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree
  add_index "milestones", ["title"], name: "index_milestones_on_title", using: :btree
  add_index "milestones", ["title"], name: "index_milestones_on_title_trigram", using: :gin

  create_table "namespaces", force: :cascade do |t|
    t.string   "name",                     null: false
@@ -580,8 +590,10 @@

  add_index "namespaces", ["created_at", "id"], name: "index_namespaces_on_created_at_and_id", using: :btree
  add_index "namespaces", ["name"], name: "index_namespaces_on_name", unique: true, using: :btree
  add_index "namespaces", ["name"], name: "index_namespaces_on_name_trigram", using: :gin
  add_index "namespaces", ["owner_id"], name: "index_namespaces_on_owner_id", using: :btree
  add_index "namespaces", ["path"], name: "index_namespaces_on_path", unique: true, using: :btree
  add_index "namespaces", ["path"], name: "index_namespaces_on_path_trigram", using: :gin
  add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree

  create_table "notes", force: :cascade do |t|
@@ -607,6 +619,7 @@
  add_index "notes", ["created_at"], name: "index_notes_on_created_at", using: :btree
  add_index "notes", ["is_award"], name: "index_notes_on_is_award", using: :btree
  add_index "notes", ["line_code"], name: "index_notes_on_line_code", using: :btree
  add_index "notes", ["note"], name: "index_notes_on_note_trigram", using: :gin
  add_index "notes", ["noteable_id", "noteable_type"], name: "index_notes_on_noteable_id_and_noteable_type", using: :btree
  add_index "notes", ["noteable_type"], name: "index_notes_on_noteable_type", using: :btree
  add_index "notes", ["project_id", "noteable_type"], name: "index_notes_on_project_id_and_noteable_type", using: :btree
@@ -705,9 +718,12 @@
  add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree
  add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree
  add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
  add_index "projects", ["description"], name: "index_projects_on_description_trigram", using: :gin
  add_index "projects", ["last_activity_at"], name: "index_projects_on_last_activity_at", using: :btree
  add_index "projects", ["name"], name: "index_projects_on_name_trigram", using: :gin
  add_index "projects", ["namespace_id"], name: "index_projects_on_namespace_id", using: :btree
  add_index "projects", ["path"], name: "index_projects_on_path", using: :btree
  add_index "projects", ["path"], name: "index_projects_on_path_trigram", using: :gin
  add_index "projects", ["runners_token"], name: "index_projects_on_runners_token", using: :btree
  add_index "projects", ["star_count"], name: "index_projects_on_star_count", using: :btree
  add_index "projects", ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree
@@ -785,7 +801,9 @@
  add_index "snippets", ["author_id"], name: "index_snippets_on_author_id", using: :btree
  add_index "snippets", ["created_at", "id"], name: "index_snippets_on_created_at_and_id", using: :btree
  add_index "snippets", ["created_at"], name: "index_snippets_on_created_at", using: :btree
  add_index "snippets", ["file_name"], name: "index_snippets_on_file_name_trigram", using: :gin
  add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree
  add_index "snippets", ["title"], name: "index_snippets_on_title_trigram", using: :gin
  add_index "snippets", ["updated_at"], name: "index_snippets_on_updated_at", using: :btree
  add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree

@@ -919,9 +937,12 @@
  add_index "users", ["created_at", "id"], name: "index_users_on_created_at_and_id", using: :btree
  add_index "users", ["current_sign_in_at"], name: "index_users_on_current_sign_in_at", using: :btree
  add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
  add_index "users", ["email"], name: "index_users_on_email_trigram", using: :gin
  add_index "users", ["name"], name: "index_users_on_name", using: :btree
  add_index "users", ["name"], name: "index_users_on_name_trigram", using: :gin
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
  add_index "users", ["username"], name: "index_users_on_username", using: :btree
  add_index "users", ["username"], name: "index_users_on_username_trigram", using: :gin

  create_table "users_star_projects", force: :cascade do |t|
    t.integer  "project_id", null: false