为什么在oracle SQL中,在条件差异很大的情况下,为同一列执行具有两个不同值的查询所花费的时间

时间:2017-07-18 06:30:26

标签: sql oracle performance query-optimization

我们假设我们有一名员工。我在这张桌子上执行了2个以下的查询。

查询1

select * from employee where email_id = 'admin@xyz.com'

查询2

select * from employee where email_id = 'abc@xyx.com'

假设我有一个巨大的数据集,我正在执行此查询。观察是Query1比Query2花费的时间少得多。我还检查了列email_id上没有索引。我的假设是服务器以某种方式缓存Query1而不是Query2。如果这是真的那么我如何强制服务器缓存Query2?另外,如果可能的话,我想在不使用索引的情况下优化Query2。有什么建议吗?

2 个答案:

答案 0 :(得分:1)

如果没有email_id上的索引,我们会希望两个查询花费相同的时间,即在employees表上执行全表扫描所花费的时间。那么为什么一个查询的返回速度比另一个快得多呢?

假设:

  1. 您的查询确实使用硬编码值,而不是绑定变量(即 select * from employee where email_id = ':1')。
  2. 性能更高的查询确实在搜索admin电子邮件地址。
  3. 包含文字的查询通常是一件坏事:每个版本都必须进行硬解析,它们会占用游标缓存中的空间。但它们也可能有不同的执行路径(因为它们是单独解析的)或性能配置文件。这似乎就是这种情况。如果没有索引,访问路径将是相同的,但由于缓存,总耗用时间可能会有所不同。

    可能有两种可能的缓存。

    1. 意外缓存。包含employee admin@xyz.com记录的块已经在数据库缓冲区缓存中,因此查询不必读取整个表。
    2. 故意缓存。有些人使用resultset caching通过电子邮件地址查询员工,employee的{​​{1}}记录会缓存在那里。
    3. 因此,可以缓存admin@xyz.com的两个原因。显然,任何员工都可能如此。但似乎人们会比admin@xyz.com更频繁地寻找admin@xyz.com。很简单,(不知道您的应用程序或您的数据),管理员用户经常被查询,因此比任何其他随机用户更有可能在缓存中。

        

      "如何强制服务器缓存Query2?"

      如果joe.soap@xyz.com用户被意外缓存 - 它只是在缓冲区保持温暖,因为它经常被查询 - 你真的不能做多少。确实,我们可以将表格固定在内存中,但这通常是一个坏主意。大多数情况下,数据库是一个比我们更好的资源管理器:如果块没有保留在DB Buffer Cache中,因为它们不经常使用(假设DBC是大小正确)。

      如果您的应用程序正在使用结果集缓存,那么您可以显式检索admin的记录。但是你不能为所有用户做到这一点,原因与以前一样:如果经常使用记录,你就不想将记录固定在内存中。

      这为我们带来了目标。你想在这里优化什么?用户子集的访问时间/或任何用户的访问时间?如果是后者,则需要abc@xyz.com上的索引。

答案 1 :(得分:0)

更多假设:

  1. 一旦你运行了query2,它就会出现在你的缓冲区缓存中,第二次你运行它就会有一个缓存命中,除非你以后再运行它并且它已经老化了。
  2. 您正在使用cursor_sharing = FORCE强制系统绑定
  3. 你有一个很好的理由不在email_id上使用索引。你真的,真的想好好利用索引。
  4. 将来如何查询query3和query4等?