2017-01-27 5 views
0

私は一日一束の価格データをグラフにしています。 1日に株式取引を考える。私が何をしたいかDjango:340個の重複したクエリを削除して効率的なクエリを作成する

  • によって取引が一般的な傾向

問題を示すために、価格の平均線を表示する表示

クエリでDjango Debug Toolbarを見ると、次のように表示されます。

  • 346は、実際のクエリを見てみると
  • 1498.11ms
  • を照会し、私はそれが毎日照会など)(get_querysetのために、 "340回複製" を参照してください。
  • これをより効率的にして重複がないようにするにはどうすればよいですか?できるだけ効率的にする方法に関するヒントやトリックは大いにありがたく思っています。私は、オブジェクトの価格が返さグラフに必要なデータを返すために作ったGraphViewから継承ビューを持っている

    :どのよう

。この要求により、何千もの結果が返される可能性があるので、このクエリをできるだけ効率的にすることがロード時間にとって重要です。使用

ツール:

  • ジャンゴ1.10.1
  • Postgresの
  • Plotlyテンプレート
  • Djangoのデバッグツールバーの結果

ビュー&クエリをグラフ化します:

class GraphView(TemplateView): 

    def get_dates(self): 
     dates = [] 
     if self.get_queryset(): 
      start = self.get_queryset()[0][2].date() 
      end = datetime.today().date() 
      delta = end - start 
      for i in range(delta.days + 1): 
       dates.append(start + timedelta(days=i)) 
     return dates 

    def trend_line(self): 
     trades = self.get_queryset() 
     dates = self.get_dates() 
     data_x = [] 
     data_y = [] 

     for date in dates: 
      subset = trades.filter(date_of_price__date=date) 
      prices_for_day = subset.aggregate(Avg('price')) 
      if prices_for_day['price__avg'] > 0: 
       data_x.append(date.strftime('%Y-%m-%d')) 
       data_y.append(prices_for_day['price__avg']) 
     return data_x, data_y 

    def get_context_data(self, **kwargs): 
     context = super(GraphView, self).get_context_data(**kwargs) 
     x_axis_date = [] 
     y_axis_price = [] 
     bubble_text = [] 
     for trade in self.get_queryset(): 
      x_axis_date.append(trade[2].date().strftime('%Y-%m-%d')) 
      y_axis_price.append(int(trade[1])) 
      desc = "#%s" % (trade[0]) 
      bubble_text.append(str(desc.encode('ascii', 'ignore'))) 

     trend_data_x, trend_data_y = self.trend_line() 

     try: 
      x_axis_date_start = x_axis_date[0] 
     except IndexError: 
      x_axis_date_start = None 

     try: 
      x_axis_date_end = x_axis_date[-1] 
     except IndexError: 
      x_axis_date_end = None 

     context.update({ 
      "x_axis_date": x_axis_date, 
      "x_axis_date_start": x_axis_date_start, 
      "x_axis_date_end": x_axis_date_end, 
      "y_axis_price": y_axis_price, 
      "bubble_text": bubble_text, 
      "trend_data_x": trend_data_x, 
      "trend_data_y": trend_data_y, 
     }) 
     return context 


class ReferenceDetailView(StaffuserRequiredMixin, SetHeadlineMixin, GraphView): 
     headline = "Variation Detail" 
     template_name = "ref_trades/reference_detail.html" 

     def get_reference_model(self): 
      return get_object_or_404(ReferenceModel, pk=self.kwargs["pk"]) 

     def get_headline(self): 
      return "%s" % self.get_reference_model() 

     def get_queryset(self): 
      return TradeModel.objects.filter(
       date_of_price__gte=datetime.now() - timedelta(days=365), 
       reference_model__id=self.kwargs["pk"] 
      ).exclude(price=0).values_list('id', 'price' , 'date_of_price', 'title') 

はあなたの助けをありがとうありがとう!

+0

に応じて最善のアプローチであってもなくてもよいですか? – Sayse

+0

devのためにローカルではありません – Emile

+0

それはDDTが拾い上げる問題である可能性が高くなります。少なくともdevの 'LocMemCache'を有効にしたいかもしれません。唯一の他のiffyポイントは、 'data_points'のforループのクエリです。 – Sayse

答えて

1

1日あたりのクエリを実行するのではなく、日付順に並べ替えられたすべてのオブジェクトを取得し、itertools.groupby()を使用してそれらを日付に分割することができます。

def data_points(self): 
    trades = self.get_queryset() 
    data_x = [] 
    data_y = [] 

    for date, subset in itertools.groupby(trades, lambda t: t.date): 
     average_price = average(subset) # average() needs to be implemented 
     if average_price > 0: 
      data_x.append(date.strftime('%Y-%m-%d')) 
      data_y.append(average_price) 
    return data_x, data_y 

このアプローチは、DB CPU/IOのためのWebサーバーのCPUの売買、これがまたはあなたがキャッシュを使用していますあなたのインフラ

+0

Iainに感謝します。groupbyは大いに助けました。結果:22msで5つのクエリ!もう一度、ありがとう、ありがとう! – Emile

関連する問題