我有城市列表,大约有2712406条记录。每个都有州代码,用户首先选择州代码。
StateCode和Name都已编入索引。
我当前对数据库的查询以/cities?code=[StateCode]&name=[Alphabets]
哪个内部翻译为
return db.Cities.Where(x=>x.StateCode == stateCode && x.Name.StartsWith(name))
.OrderBy( x=> x.Name )
.Take(10);
当数据库忙于进行更大的操作时,此查询会超时。
我想到了两种方式,
存储S3对象
我计算出用户需要的组合总数为1000万。假设只有5KB的JSON用于检索前10个城市。它需要50GB的存储空间。大约每月5美元左右。哪个好,但是如果我将我的json存储为/stateCode/a /stateCode/b
等对于使用CDN的用户来说会更快?
结合州和城市密钥
假设我有一个单独的列合并,索引为“StateCode / Name”。 在这里,我知道查询将命中B + Tree索引。在一个列索引上查找是否会有更大的好处,或者它与当前查询几乎相同,我最好使用S3。我不知道S3是否会提供与DB相同的性能,我所能做的就是在每个应用服务器中设置多个readonly DB。
答案 0 :(得分:1)
关于在SQL DB中组合State和City Key:如果将列分开,也可以使用B + Tree索引。您只需要使用[combined | concatenated | multi-column]索引。 E.g。
CREATE INDEX blah ON cities (statecode, name);
注意:一个索引包含两个列。与非精确运算符(StartWith
而不是等于)一起使用的列最后一次。
如果StartWith方法转换为SQL,则此索引支持您的查询:
SELECT name
FROM cities
WHERE state = ?
AND name LIKE 'b%'
如果以另一种方式实施StartsWith
,您可能需要摆弄以获得正确的响应时间。最好是打开SQL查询日志记录并查看。您的ORM工具很可能会将StartsWith
转换为无法正确使用此索引的内容,但它可能很容易解决,因此它可以正常运行(并且速度很快)。
ps:你正在使用“take(10)”而没有给出ORDER BY(sql),这会产生不确定的结果。
pps。:我发现S3的想法也很有趣;)
答案 1 :(得分:0)
事实证明,TEXT INDEX组合效果很好。加入是昂贵的操作。
查询比两个不同结果集的AND更好。
@CityPath = StateCode + '/' + CharactersTyped + '%'
SELECT TOP 10 * FROM Cities WHERE CityPath LIKE @CityPath
在上面的查询中,B +索引必须搜索有限的子树,因为StateCode本身就是根。但是在以下查询中,B + index必须搜索更大的子树,并且必须比较StateCode等效性的每个结果。 CityName搜索的B +索引扫描的结果集在第二个查询中较大,这导致微秒超时。
@StateCode = StateCode
@CityName = CharactersTyped
SELECT TOP 10 * FROM Cities WHERE CityName LIKE @CityName
AND StateCode = @StateCode
如果数据存在于层次结构中,计算列索引可以改善数据搜索,如上所示。