2016-08-09 7 views
0

私のアプリは現在、約1280万行のテーブルを持っていて、そのテーブルはhas_oneという別の5つのテーブルと関連付けられています。Railsのデータベースクエリが極端に遅い

これらのデータはすべて、filterrific gemを使用してフィルタリング機能を備えたテーブルに表示されます。問題は、列固有の検索のようなクエリを実行するには時間がかかりすぎるのに対し、Table.countクエリは30-40秒ほどかかることがあります。クエリ時間を大幅に短縮するクエリ最適化手法はありますか?

私は熱心な負荷を実装し、表示するために必要な列を選択しようとしましたが、パフォーマンスの向上はそれほど重要ではありませんでした。

例スキーマ:検索フィルタの

domain.rb

create_table "domains", force: :cascade do |t| 
    t.string "name",          null: false 
    t.integer "age",      default: 0 
    t.integer "pr",      default: 0 
    t.boolean "dmoz",      default: false 
    t.float "price",     default: 0.0 
    t.string "listing_type" 
    t.datetime "created_at",        null: false 
    t.datetime "updated_at",        null: false 
    t.string "source" 
    t.datetime "end_date_time" 
    t.integer "no_bids",     default: 0 
    t.float "traffic",     default: 0.0 
    t.float "valuation",    default: 0.0 
    end 
add_index "domains", ["name"], name: "index_domains_on_name", unique: true, using: :btree 

、スコープが使用され、以下の例:およその行数を取得する

scope :basic, lambda { |basic| 
    query = "" 
    query += "age BETWEEN #{check_min(basic.age_min.to_i)} AND #{check_max(basic.age_max.to_i)} " if basic.age_min.present? || basic.age_max.present? 
    query += "AND price BETWEEN #{check_min(basic.price_min.to_f)} AND #{check_max(basic.price_max.to_f)} " if basic.price_min.present? || basic.price_max.present? 
    query += "AND pr BETWEEN #{check_min(basic.pr_min.to_i)} AND #{check_max(basic.pr_max.to_i)} " if basic.pr_min.present? || basic.pr_max.present? 
    if query[0..2] == 'AND' 
     query = query[3..-1] 
    end 

    where(query) 
    } 
+0

スキーマとその検索方法に関する詳細情報を提供できますか?あなたがより良い/より良いインデックスを必要とするように聞こえるが、詳細がなければ、何がスピードアップするかは言い難い。 – rdubya

+0

最適化したいのですか?テーブルのサイズを考えると、カウントに十分な近似値ですか? –

+0

ねえ、私はいくつかの追加の詳細を追加しました。可能であれば、カウントとクエリの両方をスピードアップしたいと思います。 @ChrisTraversは時間を大幅に短縮すれば、おおよその値で十分でしょう。どのようにして近似値を得ることができますか? –

答えて

0

、 SQLで次のように行う

SELECT reltuples AS approximate_row_count 
    FROM pg_class WHERE relname = 'domains'; 

ここでは生成されたSQLまたはクエリのプランを提供していないので、ここに行くための一般的なアドバイスがあります。私は、より多くの情報が入ってくるので少し具体的なアドバイスを追加するかもしれませんが、それはいくぶん限定されています。

SQLは宣言型言語です。つまり、dbに必要な情報を伝え、それが高速に実行できることを確認することを意味します。だからあなたがしたいのは、遅いステートメント(あなたのpostgresql.confにlog_min_duration_statement)を記録して、それらのステートメントを分析することです。クエリプランがなければ、どのインデックスが必要なのかを知ることは非常に困難です。

クエリプランは基本的に、使用可能なインデックスがあれば、必要なデータを取得する最も早い方法であるとPostgreSQLが決定したことを示しています。そこから、予期せず大規模なテーブルに逐次スキャンを実行する場合、選択基準(つまり、最も多くの行を切り取る方法)を参照し、それらのフィールドのインデックスを作成することをお勧めします。ただし、通常、シーケンシャルスキャンは通常10%テーブルの)。

関連する問題