أفضل طريقة لتحديد أي من مجموعة من المفاتيح الموجودة في مخزن البيانات

StackOverflow https://stackoverflow.com/questions/1607126

سؤال

ولدي بضع مئات من مفاتيح، كل من الطراز نفسه، التي أشرت قبل احتساب:

candidate_keys = [db.Key(...), db.Key(...), db.Key(...), ...]

وبعض هذه المفاتيح الرجوع إلى الجهات الفعلية في مخزن البيانات، والبعض الآخر لا. وأود أن تحديد مفاتيح لا تتوافق مع الكيانات.

وليس من الضروري أن نعرف البيانات داخل الكيانات، فقط ما إذا كانت موجودة.

وحل واحد سيكون لاستخدام db.get ():

keys_with_entities = set()
for entity in db.get(candidate_keys):
  if entity:
    keys_with_entities.add(entity.key())

ولكن سيكون هذا الإجراء جلب جميع البيانات كيان من مخزن والتي هي غير ضرورية ومكلفة.

ووالفكرة الثانية هي استخدام استعلام مع عامل تصفية IN على key_name، جلب يدويا في قطع 30 لتناسب متطلبات IN الزائفة التصفية. ومع ذلك لا يسمح للاستفسار مفاتيح فقط مع مرشح IN.

هل هناك طريقة أفضل؟

هل كانت مفيدة؟

المحلول

في مرشحات غير معتمدة مباشرة من قبل محرك مخزن البيانات التطبيقات. انهم راحة وهذا ما تنفذ في المكتبة العميل. تتم ترجمة استعلام IN مع 30 القيم في 30 استفسار المساواة في قيمة واحدة لكل منهما، مما أدى إلى 30 استفسار العادية!

ونظرا لأوقات ذهابا وإيابا وعلى حساب من الاستفسارات حتى مفاتيح فقط، وأظن أنك سوف تجد أن مجرد محاولة لجلب جميع الكيانات في دفعة واحدة إحضار هو الأكثر كفاءة. إذا الكيانات الخاصة بك كبيرة، ومع ذلك، يمكنك إحراز المزيد من التحسين: للحصول على كل كيان قمت بإدراج، إدراج "جود" كيان فارغ وهو طفل من هذا الكيان، واستخدام ذلك في الاستعلامات. على سبيل المثال:

foo = AnEntity(...)
foo.put()
presence = PresenceEntity(key_name='x', parent=foo)
presence.put()
...
def exists(keys):
  test_keys = [db.Key.from_path('PresenceEntity', 'x', parent=x) for x in keys)
  return [x is not None for x in db.get(test_keys)]

نصائح أخرى

وعند هذه النقطة، فإن الحل الوحيد لدي هو يدويا الاستعلام عن طريق مفتاح مع keys_only=True، مرة واحدة في المفتاح.

for key in candidate_keys:
  if MyModel.all(keys_only=True).filter('__key__ =', key).count():
    keys_with_entities.add(key)

وهذا قد يكون في الواقع أبطأ بعد ذلك فقط تحميل الكيانات دفعة واحدة والتخلص منها، على الرغم من أن الحمل دفعة المطارق أيضا حصة Data Received from API.

كيف لا تفعل ذلك (تحديث على أساس الجواب نيك جونسون):

وأنا على النظر أيضا إضافة معلمة خصيصا لغرض التمكن من مسح لأنها مع مرشح IN.

class MyModel(db.Model):
  """Some model"""
  # ... all the old stuff
  the_key = db.StringProperty(required=True) # just a duplicate of the key_name

#... meanwhile back in the example

for key_batch in batches_of_30(candidate_keys):
  key_names = [x.name() for x in key_batch]
  found_keys = MyModel.all(keys_only=True).filter('the_key IN', key_names)
  keys_with_entities.update(found_keys)

والسبب ينبغي تجنب ذلك هو أن المرشح IN على بالتتابع الملكية ينفذ مسح مؤشر، بالإضافة إلى البحث مرة واحدة لكل بند في مجموعة IN الخاص بك. كل بحث يأخذ 160-200ms بحيث يصبح بسرعة كبيرة عملية بطيئة للغاية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top