← Back to team overview

yahoo-eng-team team mailing list archive

[Bug 1374044] Re: _make_subnet_dict lazy loads not required attibutes causing high number of not required sql query

 

** Changed in: neutron
       Status: Fix Committed => Fix Released

-- 
You received this bug notification because you are a member of Yahoo!
Engineering Team, which is subscribed to neutron.
https://bugs.launchpad.net/bugs/1374044

Title:
  _make_subnet_dict lazy loads not required attibutes causing high
  number of not required sql query

Status in OpenStack Neutron (virtual network service):
  Fix Released

Bug description:
  The get_active_networks_info rpc call causes high number of sql query.
  For example the following query

  SELECT subnetroutes.destination AS subnetroutes_destination, subnetroutes.nexthop AS subnetroutes_nexthop, subnetroutes.subnet_id AS subnetroutes_subnet_id 
  FROM subnetroutes 
  WHERE %s = subnetroutes.subnet_id

  was used on this trace:

    File "/usr/lib/python2.7/site-packages/eventlet/greenpool.py", line 82, in _spawn_n_impl
      func(*args, **kwargs)
    File "/opt/stack/new/neutron/neutron/openstack/common/rpc/amqp.py", line 462, in _process_data
      **args)
    File "/opt/stack/new/neutron/neutron/common/rpc.py", line 45, in dispatch
      neutron_ctxt, version, method, namespace, **kwargs)
    File "/opt/stack/new/neutron/neutron/openstack/common/rpc/dispatcher.py", line 172, in dispatch
      result = getattr(proxyobj, method)(ctxt, **kwargs)
    File "/opt/stack/new/neutron/neutron/db/dhcp_rpc_base.py", line 92, in get_active_networks_info
      networks = self._get_active_networks(context, **kwargs)
    File "/opt/stack/new/neutron/neutron/db/dhcp_rpc_base.py", line 42, in _get_active_networks
      plugin.auto_schedule_networks(context, host)
    File "/opt/stack/new/neutron/neutron/db/agentschedulers_db.py", line 211, in auto_schedule_networks
      self.network_scheduler.auto_schedule_networks(self, context, host)
    File "/opt/stack/new/neutron/neutron/scheduler/dhcp_agent_scheduler.py", line 114, in auto_schedule_networks
      subnets = plugin.get_subnets(context, fields=fields)
    File "/opt/stack/new/neutron/neutron/db/db_base_plugin_v2.py", line 1333, in get_subnets
      page_reverse=page_reverse)
    File "/opt/stack/new/neutron/neutron/db/db_base_plugin_v2.py", line 209, in _get_collection
      items = [dict_func(c, fields) for c in query]
    File "/opt/stack/new/neutron/neutron/db/db_base_plugin_v2.py", line 931, in _make_subnet_dict
      for route in subnet['routes']],
    File "/opt/stack/new/neutron/neutron/openstack/common/db/sqlalchemy/models.py", line 57, in __getitem__
      return getattr(self, key)
    File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/attributes.py", line 237, in __get__
      return self.impl.get(instance_state(instance), dict_)
    File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/attributes.py", line 590, in get
      value = self.callable_(state, passive)
    File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/strategies.py", line 529, in _load_for_state
      return self._emit_lazyload(session, state, ident_key, passive)
    File "<string>", line 1, in <lambda>
    File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/strategies.py", line 598, in _emit_lazyload
      result = q.all()
    File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/query.py", line 2363, in all
      return list(self)
    File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/query.py", line 2480, in __iter__
      return self._execute_and_instances(context)
    File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/query.py", line 2495, in _execute_and_instances
      result = conn.execute(querycontext.statement, self._params)
    File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/base.py", line 730, in execute
      return meth(self, multiparams, params)
    File "build/bdist.linux-x86_64/egg/sqlalchemy/sql/elements.py", line 322, in _execute_on_connection
      return connection._execute_clauseelement(self, multiparams, params)
    File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/base.py", line 827, in _execute_clauseelement
      compiled_sql, distilled_params
    File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/base.py", line 913, in _execute_context
      tb = str(traceback.format_stack())

  1. dhcp_agent_scheduler.py explicitly specifies he is interested only in two fields ['network_id', 'enable_dhcp']
  https://github.com/openstack/neutron/blob/ee4f94e32c8422eb5785f0bb1eb39b94b4e9b064/neutron/scheduler/dhcp_agent_scheduler.py#L103
  2. _get_collection makes lazy query (not fetching every related data)
  3.  make_subnet_dict  forces the ORM to post load not required filed
  https://github.com/openstack/neutron/blob/ee4f94e32c8422eb5785f0bb1eb39b94b4e9b064/neutron/db/db_base_plugin_v2.py#L830
  4. The self._fields  drops the lazy fetched fields.

  So the Db api provides the interface for efficient selective DB load,
  but at the and it does one of the most inefficient thing is doable on
  listing. Issues new SQL SELECt statements  per row/object.

  Looks like all function does similar thing which uses the self._field method.
  The make dict methods MUST NOT try to fetch the not requested fields from the data object at all.
  In this case the post _filter method also a not needed.

To manage notifications about this bug go to:
https://bugs.launchpad.net/neutron/+bug/1374044/+subscriptions


References