我正在开发一个在Windows Mobile 6上运行的应用程序,它需要能够从项目表格中检索包含给定字符串(由最终用户提供)的项目表中的所有项目.问题是表中大约有170,000个项目.由于我需要在描述中的任何位置返回包含字符串的所有项目,因此我不得不使用LIKE%string%,这样就无法使用索引.数据和表结构最初基于Progress数据库,它在任何单词索引字段上都有一个精彩的包含运算符.我们的移动应用程序不是这种情况,因为它使用的是SQL Server Compact 3.5.
基本上,我的DAL运行查询并检索SqlCeDataReader,然后使用ItemFactory创建仅包含匹配项的List对象.这显然可以让我们将域/业务对象与数据访问层分开.
精细和花花公子,除了在我搜索描述中包含类似"高尔夫"之类的所有项目时检索项目所需的8米和42秒.显然,这不是最终用户可接受的时间范围.
我的第一次尝试是使用SELECT*FROM Item"(在其中一个主索引字段上使用order by子句)从数据库中检索所有项目.此时,我在运行SqlCeDataReader时运行了IndexOf检查如果项目包含所请求的描述文本,则ItemFactory仅向List对象添加项目.这将速度提高到1m 46s.不是太破旧,但仍然太慢.
然后我尝试了另一种显示出承诺的方法......几乎......当应用程序启动时,我尝试创建一个包含数据库中所有项目对象的List(大约需要2分钟来运行查询并填充整个列表,但是至少它只是一次,因为应用程序正在初始化......仍然......呃).一旦列表完成,我可以轻松地在该列表上运行查询,执行以下操作(我希望我的语法正确...我现在不工作,我没有在PC上使用Visual Studio我坐在那里:
List<Item> specificItems =
AllItems.FindAll(i => i.Description.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0);
Run Code Online (Sandbox Code Playgroud)
这种方法将其降至21秒.非常好(虽然在宏伟的计划中仍然很慢).但是,问题是如果我从数据库加载所有项目,内存使用量太大了.在初始加载期间,我必须切断最后20,000个项目(所以21s时间框架可能更像是25s),因为抛出了OutOfMemoryException.根据模拟器上的内存管理器,我仍然有大约20 MB的空闲RAM,但我听说一个进程只能有32 MB或RAM相关联(不确定WM 6是否属实,但它出现了所以).
为了确保它不是因为我使用List对象来保存所有项目(我在构造函数中实例化了所需的容量以避免动态调整大小),我也读过它可能会导致额外的内存使用量implicity调用EnsureCapacity,我尝试使用Item []数组(提前调整大小).这仍然存在内存问题,尺寸差异可以忽略不计.
好吧漫无边际.我知道我可能会有一些如何限制datareader从数据库返回的记录(通过对不同类型字段的一些索引搜索),然后可能会在较小的项目子集上使用indexOf来获得最大性能(因此一起跳过Like运算符).这将导致最终用户不仅必须输入描述搜索(可能是项目层次结构信息以限制在其中搜索的项目类型).
有任何想法吗?我是以错误的方式来做这件事的吗?
谢谢你的聆听(对不起这篇文章很长,我有点大声思考).
哦,我应该添加(只是总结)我正在使用的东西:
更新:虽然下面提到的Bloom Filter方法看起来很有趣,但我无法满足一个要求(我上面没有真正说明).我无法真正匹配其他词语中包含的词语(例如"俱乐部"不会返回"俱乐部").因此,我被迫完全使用不同的方法(Kent Fredric ......感谢你指出这一点).我已经将Kent的答案标记为正确,因为他的方法是满足最多要求的(Mitch,你的问题与Jaunder建议的Bloom过滤器类似).但是,我采用了不同的方法(现在......),而不是他的方式.
我所做的是将所有项目对象拉入内存,只有项目编号和描述(这使其保持在内存限制之下,但它仍然会导致比我喜欢的更长的初始化...多线程并在后台加载该信息而应用程序正在运行可以照顾我猜).为了执行搜索,我编写了自己的包含例程.该例程使用非托管c#代码编写,该代码使用两个指针和几个循环来运行描述和所需的匹配文本.如果它在描述中的任何位置找到匹配项,则会将项目编号添加到数组中.搜索完所有项目后,新查询将返回到数据库并仅捕获匹配的项目编号(由于整数字段上的索引,该编号非常快).然后,这些项目在List中创建,包含所有信息(不仅仅是项目编号和描述).整个操作大约需要5-10秒(取决于描述),这对于现在来说已经足够了.
我仍然会考虑进一步优化它(可能能够跟踪搜索项的字符数...如果项目描述中剩余的字符少于所需的文本,则循环可以继续直接到下一个项目) .
任何建议仍然欢迎.现在我已将肯特的答案标记为我的问题"最正确".
向Dolch道具,帮助我编写包含例程.
performance memory-management windows-mobile sql-server-ce sql-like
我在ado.net实体框架中的实体中遇到了一些问题.基本上我正在做的是:
var results = (from c in companies
where c.Name.StartsWith(letter)
select c);
Run Code Online (Sandbox Code Playgroud)
并将其转换为SQL,如:
WHERE (CAST(CHARINDEX(@p, [Extent1].[Name]) AS int)) = 1
Run Code Online (Sandbox Code Playgroud)
这很好,但我的表有数百万的记录,所以这运行非常慢.我需要它生成的是:
WHERE Name LIKE @p + '%'
Run Code Online (Sandbox Code Playgroud)
我搜索高低,除了使用存储过程或使用实体sql之外无法找到任何解决方案...
有没有办法通过linq做到这一点?可能通过某种方式将linq扩展到实体linq提供程序,或以某种方式拦截命令树或生成的查询?
我有一个街道名称列表,我想选择以"Al"开头的所有内容.在我的mysql中,我会做类似的事情
SELECT * FROM streets WHERE "street_name" LIKE "Al%"
Run Code Online (Sandbox Code Playgroud)
使用php的mongodb怎么样?
我在一个语句中使用了一个LIKE而不是LIKE的named_scope.与使用REGEXP相比,这在执行方面更快吗?
named_scope :order_search, :order => "name LIKE '%urgent%' AND name NOT LIKE '%not urgent%' DESC, created_at DESC"
Run Code Online (Sandbox Code Playgroud) 我试图在表中查询有限的结果集,以便在javascript中填充自动完成字段.因此,我使用LIKE运算符输入了部分字符串.
例如,如果我有一个表,例如:
tblPlaces
id country
1 Balanca
2 Cameroon
3 Canada
4 Cape Verde
5 Denmark
Run Code Online (Sandbox Code Playgroud)
为了这个例子,让我们说我想要返回两行 - 是的,对于这个例子,我在那里组建了一个国家;)我想优先考虑在国家开头匹配部分字符串的任何实例.我开始使用的查询是:
SELECT id, country FROM tblPlaces WHERE country LIKE 'ca%' LIMIT 2
Run Code Online (Sandbox Code Playgroud)
这按预期返回"喀麦隆"和"加拿大".但是,如果没有两个名称在一个单词的开头匹配字符串(例如'de'),我希望它在单词的其他地方查找.所以我修改了查询成为
SELECT id, country FROM tblPlaces WHERE country LIKE '%ca%' LIMIT 2
Run Code Online (Sandbox Code Playgroud)
然后返回'佛得角'和'丹麦',但这样做打破了我原来的'ca'搜索,现在返回'Balanca'和'喀麦隆'.
所以,我的问题是,如何使用单个查询来优先处理单词开头的匹配(也许我需要使用REGEXP?)我还假设如果'country'列被索引,这些比赛将至少以随后的字母顺序返回(即加拿大之前的喀麦隆等).
我将如何在doctrine odm中从SQL模拟类似运算符?
用例:我想在变量$ search中找到字段字幕字符串中的某个主题.
查询怎么样?
谢谢你的所有答案
我有两个字符串(它们最终将在一个简单的数据库中描述),让我们说它们是
我正在寻找的是这个.我想要一个输入"cocnut"的函数,输出为"String A"
我们可能在资本化方面存在差异,拼写并不总是存在.如果你愿意的话,目标是"快速而肮脏"的搜索.
是否有任何.net(或第三方),或为字符串推荐'相似算法',所以我可以检查输入是否有"非常接近的片段"并返回它?我的数据库将有50个条目,顶部.
我有一个应该包含所有顶级和二级域名的数据库.但我正在解析的提要包含很多子文件夹,我想删除包含任何%符号的任何行,但我很难弄清楚如何使用百分号作为字段我' d喜欢匹配,同时仍然使用LIKE功能.以下是我正在尝试使用的代码:
select FROM `001ProductList` WHERE programURL LIKE '%%%'
Run Code Online (Sandbox Code Playgroud)
以下是我想要匹配的示例:
www.site.com%3Ack-5941560-10463497?URL = HTTP%3A%2F%2Fwww.example.com%2Fproddetail.aspx%...
如果我遇到一个带有%符号的行,我想删除它.
我在SQL-Server表中有批量数据.其中一个字段包含以下数据:
'(?? ?????!) ??? ?? ???? ?????)'
Run Code Online (Sandbox Code Playgroud)
尝试:
SELECT * from Ayyat where Data like '%?????%' ;
Run Code Online (Sandbox Code Playgroud)
但它显示没有结果.
我正在尝试使用带有星号的"Like"过滤记录,它在使用Access 2010返回许多记录时起作用.我很难过,为什么它与ADO一起使用时没有返回任何内容.代码包括多个表和列,以便进行故障排除我做了一个简单的查询.这是代码:
strsql = "SELECT tproducts.Prod_Name FROM tproducts " _
& " WHERE tproducts.Prod_Name Like " & Chr(34) & "SO*" & Chr(34)
Set cn = New ADODB.Connection
cn = connString
cn.Open
Set rs = New ADODB.Recordset
rs.Open strsql, cn, adOpenStatic, adLockOptimistic
' test here
iRecCount = rs.RecordCount
rs.MoveFirst
Run Code Online (Sandbox Code Playgroud)
Recordcount返回-1.
当"Like"被"equals"替换时,它返回正确的记录,所以我确信它能够连接到数据库,例如:
strsql = "SELECT tproducts.Prod_Name FROM tproducts " _
& " WHERE tproducts.Prod_Name = " & Chr(34) & "SONY Vaio SVD13213CXB" & Chr(34)
Run Code Online (Sandbox Code Playgroud)
有没有一种特殊的方法在ADO中使用Like运算符?
我可以通过哪些其他方式过滤以获得与使用"赞"相同的结果?例如,要查找所有" SVD "产品?