2014-06-18 86 views
1

我正在使用數據存儲本機api訪問gae數據庫(爲了充分研究的具體原因)。我想優化代碼並在我的請求中使用memcache,而不是直接獲取值,問題在於我的查詢是排序的。如何排序優化鍵只查詢

當我做我的查詢findProductsByFiltersQuery.setKeysOnly();,我收到此錯誤:

The provided keys-only multi-query needs to perform some sorting in memory. As a result, this query can only be sorted by the key property as this is the only property that is available in memory.

的weired事情是,它開始從要求有一定的複雜情況發生,比如這個請求失敗:

SELECT __key__ FROM Product WHERE dynaValue = _Rs:2 AND productState = PUBLISHED AND dynaValue = _RC:2 AND dynaValue = RF:1 AND dynaValue = ct:1030003 AND dynaValue = _RS:4 AND dynaValue = _px:2 AND itemType = NEWS ORDER BY modificationDate DESC 

,而這一個通行證:

SELECT __key__ FROM Product WHERE itemType = CI AND productState = PUBLISHED ORDER BY modificationDate DESC 

可有人è爲什麼會發生這種情況,並且如果在獲取密鑰時訂購不可行,那麼該功能是什麼? :由於結果是分頁的,因此從第一個過濾請求中獲取一組錯誤的鍵是沒有用的。那麼怎麼想呢?

也請注意,當我做非keysOnly很長的請求,我收到此消息

Splitting the provided query requires that too many subqueries are merged in memory.

at com.google.appengine.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:129) 
at com.google.appengine.api.datastore.QuerySplitHelper.splitQuery(QuerySplitHelper.java:99) 
at com.google.appengine.api.datastore.QuerySplitHelper.splitQuery(QuerySplitHelper.java:71) 

有人可以解釋我怎麼可能有在內存中處理當值索引?或者它是隻有這個錯誤的devmode服務器?

+0

你能提供你用來創建查詢的代碼嗎? –

+0

我回答了你的問題,假設你的查詢實際上有一個OR,IN或!=過濾器。如果你只使用AND過濾器,你不應該得到這些錯誤。確保您的SDK是最新的,如果是,請提交錯誤:https://code.google.com/p/googleappengine/issues/entry –

回答

1

當您在數據存儲中使用OR,IN!=運算符時,內存查詢是必需的。如described in this blog post所示,使用這些運算符的查詢會在客戶端中拆分爲多個數據存儲區查詢。例如:如果添加ORDER BY B到您的查詢,這兩個子查詢得到這個順序

SELECT * FROM Foo WHERE A = 1 
SELECT * FROM Foo WHERE A = 2 

SELECT * FROM Foo WHERE A = 1 ORDER BY B 
SELECT * FROM Foo WHERE A = 2 ORDER BY B 

雖然這些

SELECT * FROM Foo WHERE A = 1 OR A = 2 

會分成兩個查詢數據存儲查詢返回按B排序的結果,查詢的並集不是。在客戶端,SDK合併來自由B排序的兩個結果。

爲了做到這一點,數據存儲查詢必須實際返回有序屬性,否則SDK將不知道合併這些屬性的正確方法一起。

如果您正在使用大量過濾器編寫查詢,請確保僅使用AND過濾器。這將允許僅在數據存儲中執行所有操作,在這種情況下,不需要內存中的分類。

+0

嗨,帕特里克,感謝您的非常明確的解釋。我仍然沒有檢查我的查詢是否包含OR運算符(因爲System.out和System之間可能存在線程同步差異。err) 無論如何,這是一條很好的探索之路。如果我真的只有AND條件,我會提交一個錯誤(但這不會幫助我解決方法:) –

+0

ps:生成查詢的代碼非常複雜,但我使用了CompositeFilterOperator.and()方法(所以乍一看不應有任何OR操作,我必須在代碼樹中進行更深入的檢查) 也許我使用!=操作符 –