SQL Scaling:当我有多个OR列条件时,我应该尝试最小化查询吗?

时间:2013-08-15 18:45:20

标签: java mysql database performance scalability

我的数据库架构是

INTEGER id
TIME_STAMP last_updated   // indexed
VARCHAR url               // indexed

// Place attributes
VARCHAR name              // indexed
VARCHAR address           // indexed
VARCHAR phone             // indexed

INTEGER score

除名称,地址和电话字段外,其中一个必须为非空,另外两个为空。

有效示例:

{name="Pizza Hut", address=null, phone=null, score=40} 

无效的例子:

{name="Pizza Hut", address="some address", phone=null, score=40} 

我正在尝试编写此功能。

// return a map/dictionary of String keys and Integer scores of latest data in DB that matches given url, and is not older than last_updated.
// example: {name=40, address=50, phone=66}
public Map getPlaceAnalysis(String name_, String address_, String phone_, String url, DateTime last_updated_);

缩放假设:

  • 此功能将被频繁调用。
  • 数据库有数百万行
  • 姓名,电话,地址可能不是我唯一的字段。我可能有20多个关于某个地方的属性。

有两种方法:

  1. 3(或关于存储在数据库中的地方的属性数)查询:

    SELECT score FROM db_name WHERE name=name_ AND url = url_ AND last_updated > last_updated_
    SELECT score FROM db_name WHERE phone=phone_ AND url = url_ AND last_updated > last_updated_
    SELECT score FROM db_name WHERE address=address_ AND url = url_ AND last_updated > last_updated_
    

    在每次查询之后,我可以选择最新的行并将分数写入我的地图/字典中,以便为相应的密钥返回。

  2. 1个查询:

    SELECT name, phone, address, score FROM db_name WHERE (name=name_ OR phone=phone_ OR address=address_ ) AND url = url_ AND last_updated > last_updated_
    

    然后我遍历查询结果,找出名称,电话和地址最新的行,并返回相应的地图/字典。

  3. 我采取哪种方法是否重要?我猜第二个更好,但我对数据库的经验很少。对不起,如果有任何解释不清楚。我想这是一个非常常见的问题,但无法弄清楚如何搜索这个问题。

1 个答案:

答案 0 :(得分:1)

当向远程数据库运行查询时,花费了大量的时间来建立连接和类似的东西,这与与数据库的通信更相关,而不是与查询本身有关。从这个角度来看,您希望最小化向数据库发出的查询数量。

正如Multiple-Column Indexes的MYSQL参考手册中所解释的那样,在您查询中使用的三个字段上创建复合索引似乎对您有利。当您仅搜索namenameaddress以及所有三个字段(请参阅最左侧前缀的内容)时,也会使用此索引,所以请注意您的订单将宣布索引。

如果可以在你的情况下使用,那么三个字段的哈希的想法似乎也很有趣。

最后,您应该阅读Understanding the Query Execution Plan和/或让数据库管理员为您提供帮助。

在谈论查询性能时要理解的关键是设计一个可重复的测试用例(即使用相同的数据集,可重复的数据库负载等),然后尝试不同的方法。并始终注意您测试的环境与生产环境之间的差异。

我希望有所帮助。