使用 AppFabric 缓存进行分页、列出和分组查询
我阅读了很多有关 AppFabric 缓存的文档,但其中大多数都涵盖了简单的场景。 例如将城市列表数据或购物卡数据添加到缓存中。 但我需要将产品目录数据添加到缓存中。
我有 4 个表:
Product(100 万行)、ProductProperty(2500 万行)、Property(100 行)、PropertyOption(300 行)
- 我使用 Product 和 ProductProperty 表的一些过滤器显示分页搜索结果查询。
- 我正在根据搜索结果集创建条件集。例如(4 项新产品、34 项电话、26 项书籍等)
- 我查询产品表的分组,其中包含 IsNew、CategoryId、PriceType 等列。
还有另一个查询,用于对包含 PropertyId 和 PropertyOptionId 列的 ProductProperty 表进行分组,以获取哪个属性有多少个项目。
因此,为了显示搜索结果,我对搜索结果进行了 1 个查询,对创建条件列表(带有计数)进行了 2 个查询,
搜索结果查询取了 0, 7 秒和 2 次分组查询总共花费了 1.5 秒。 当我运行负载测试时,我达到每秒 7 个请求,%10 被 IIS 丢弃,因为数据库无法给出响应。
这就是为什么我想缓存产品和属性记录。
如果我遵循以下项目(在 AppFabric 中);
- 创建命名缓存
- 为产品目录数据创建区域(具有 100 万行的表和具有 2500 万行的属性表)
- 用于查询数据和分组的标记项。
我可以使用某些标签进行查询并获取第一页或第二页结果吗? 我可以查询一些标签并获取一些分组结果的计数吗? (显示带有计数的过滤器选项) 我必须需要 3 台服务器吗?我可以提供一种只有一台 appfabric 服务器的解决方案吗(当然我知道风险。) 您知道有任何文章或文件解释了这些场景吗?
谢谢。
注意:
一些额外的测试: 我向缓存添加了大约 30,000 个项目,其大小为 900 MB。 当我运行 getObjectsInRegion 方法时,大约需要 2 分钟。 “IList> dataList = this.DataCache.GetObjectsInRegion(region).ToList();” 问题在于转换为 IList。如果我使用 IEnumerable 它的工作速度非常快。但是如何获得分页或分组结果而不将其转换为我的类型?
另一个测试:
我尝试获取 30.000 个产品项的分组计数,并花费 4 秒获得分组结果。例如 GetObjectByTag("IsNew").Count() 等近 50 个类似的查询。
I read a lot of documents about AppFabric caching but most of them cover simple scenarios.
For example adding city list data or shopping card data to the cache.
But I need adding product catalog data to the cache.
I have 4 tables:
Product (1 million rows), ProductProperty (25 million rows), Property (100 rows), PropertyOption (300 rows)
- I display paged search results querying with some filters for Product and ProductProperty tables.
- I am creating criteria set over searched result set. For example (4 Items New Product, 34 Items Phone, 26 Items Book etc.)
- I query for grouping over Product table with columns of IsNew, CategoryId, PriceType etc.
and also another query for grouping over ProductProperty table with PropertyId and PropertyOptionId columns to get which property have how many items
Therefore to display search results I make one query for search result and 2 for creating criteria list (with counts)
Search result query took 0,7 second and 2 grouping queryies took 1,5 second in total.
When I run load test I reach 7 request per second and %10 dropped by IIS becasue db could not give response.
This is why I want to cache Product and property records.
If I follow items below (in AppFabric);
- Create named cache
- Create region for product catalog data (a table which have 1 million rows and property table which have 25 million rows)
- Tagging item for querying data and grouping.
Can I query with some tags and get 1st or 2nd page of results ?
Can I query with some tags and get counts of some grouping results. (displaying filter options with count)
And do I have to need 3 servers ? Can I provide a solution with only one appfabric server (And of course I know risk.)
Do you know any article or any document explains those scenarios ?
Thanks.
Note:
Some additional test:
I added about 30.000 items to the cache and its size is 900 MB.
When I run getObjectsInRegion method, it tooks about 2 minutes. "IList> dataList = this.DataCache.GetObjectsInRegion(region).ToList();"
The problem is converting to IList. If I use IEnumerable it works very quicly. But How can I get paging or grouping result without converting it to my type ?
Another test:
I tried getting grouping count with 30.000 product item and getting result for grouping took 4 seconds. For example GetObjectByTag("IsNew").Count() and other nearly 50 query like that.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
遗憾的是,V1 中没有 AppFabric 的分页 API。任何批量 API(例如 GetObjectsByTag)都将在服务器上执行查询,并将所有匹配的缓存条目流回客户端。从那里您显然可以在
IEnumerable
上使用任何您想要的 LINQ 运算符(例如Skip/Take/Count
),但请注意您总是 从服务器拉回完整的结果集。我个人希望 AppFabric V2 将通过 IQueryable 而不是 IEnumerable 提供支持,这将能够将完整请求远程发送到服务器,以便它可以在返回客户端之前对结果进行分页,就像 LINQ2SQL 一样或 ADO.NET EF。
目前,一种可能的解决方案是,根据应用程序的功能,您可以在将项目注入缓存时实际计算某种分页。您可以构建代表每个页面的实体键的有序列表,并将它们作为单个条目存储在缓存中,您可以在一个请求中提取这些条目,然后单独(并行)或批量从缓存中获取列表中的项目并将它们连接在一起使用内存中 LINQ 查询。如果您想用 CPU 换取内存,只需缓存完整实体的实际列表而不是 ID,并且必须对实体进行连接。
显然,您必须想出某种键控机制来根据传入的搜索条件快速从缓存中提取这些对象列表。像这样的某种键控可能会起作用:
您可能需要考虑使用单独的进程或工作线程来执行此类操作,以保持缓存最新,而不是按需执行并在缓存条目不存在时强制用户等待尚未填充。
这种方法最终是否适合您取决于您的应用程序和数据的几个因素。如果它不完全适合您的场景,也许它至少会帮助您转变思维,以不同的方式思考解决问题。
There is, unfortunately, no paging API for AppFabric in V1. Any of the bulk APIs, like
GetObjectsByTag
, are going to perform the query on the server and stream back all the matching cache entries to the client. From there you can obviously use any LINQ operators you want on theIEnumerable
(e.g.Skip/Take/Count
), but be aware that you're always pulling the full result set back from the server.I'm personally hoping that AppFabric V2 will provide support via
IQueryable
instead of IEnumerable which will give the ability to remote the full request to the server so it could page results there before returning to the client much like LINQ2SQL or ADO.NET EF.For now, one potential solution, depending on the capabilities of your application, is you can actually calculate some kind of paging as you inject the items into the cache. You can build ordered lists of entity keys representing each page and store those as single entries in the cache which you can pull out in one request and then individually (in parallel) or bulk fetch the items in the list from the cache and join them together with an in-memory LINQ query. If you wanted to trade off CPU for Memory, just cache the actual list of full entities rather than IDs and having to do the join for the entities.
You would obviously have to come up with some kind of keying mechanism to quickly pull these lists of objects from the cache based on the incoming search criteria. Some kind of keying like this might work:
You may want to consider doing this kind of thing with a separate process or worker thread that's keeping the cache up to date rather than doing it on demand and forcing the users wait if the cache entry isn't populated yet.
Whether or not this approach ultimately works for you depends on several factors of your application and data. If it doesn't exactly fit your scenarios maybe it will at least help shift your mind into a different way of thinking about solving the problem.