存储大型城市进行自动完成查询的最佳方法是什么?

时间:2013-11-23 11:06:41

标签: sql amazon-s3 indexing

我有城市列表,大约有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);

当数据库忙于进行更大的操作时,此查询会超时。

我想到了两种方式,

  1. 在亚马逊S3上存储预先配置的查询。
  2. 将StateCode和Name合并为一列并执行SearchName.StartWith(stateCode +“/”+ name)
  3. 存储S3对象

    我计算出用户需要的组合总数为1000万。假设只有5KB的JSON用于检索前10个城市。它需要50GB的存储空间。大约每月5美元左右。哪个好,但是如果我将我的json存储为/stateCode/a /stateCode/b等对于使用CDN的用户来说会更快?

    结合州和城市密钥

    假设我有一个单独的列合并,索引为“StateCode / Name”。 在这里,我知道查询将命中B + Tree索引。在一个列索引上查找是否会有更大的好处,或者它与当前查询几乎相同,我最好使用S3。我不知道S3是否会提供与DB相同的性能,我所能做的就是在每个应用服务器中设置多个readonly DB。

2 个答案:

答案 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组合效果很好。加入是昂贵的操作。

  1. 创建列CityPath = StateCode +'/'+ CityName
  2. Index CityPath
  3. 查询比两个不同结果集的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
    
    如果数据存在于层次结构中,

    计算列索引可以改善数据搜索,如上所示。