你的数据库索引是否真的起作用了?

发表于:2018-7-31 17:03

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:toypipi luke    来源:可译网

  为了加快你的查询,增加正确的索引是必不可少的。 但是过了一段时间,当你的系统增长了,你可能会发现自己大量的索引导致数据库的写操作变慢 -- 由于每一次对表的写操作,都需要在事务中更新索引。
  也许,五年后, 你的数据库(和你的查询)在某种方式中进化,不再需要一些索引了。例如,有一些明显的情况下,这两个索引是多余的:
  -- 原设计
  CREATE INDEX ON customer (first_name);
  -- 5年后
  CREATE INDEX ON customer (first_name, last_name);
  但在许多其他情况下,事情并没有那么明显。例如…
  你可能添加了一个在外键上的索引,但随着表的增长,你的数据库开始运行更多的哈希联接,而不是嵌套循环联接,这种情况下索引并没有被使用。
  或者,你已经完全停止查询姓/名。
  或者你已经开始使用一个比实际名称更具选择性的谓词。
  或者你的客户突然都叫史密斯。
  每个人都叫史密斯-倒霉的索引!
  如果你的索引不再被使用,你可以(并且应该)删除它们。
  但如何找到未使用的索引
  如果你使用的是Oracle数据库,并且你访问的是生产系统,实际上有一个非常好的方法来查询诊断表,以便知道在游标缓存中是否有任何查询,当前正在使用你的索引。只要运行:
  SELECT sql_fulltext
  FROM v$sql
  WHERE sql_id IN (
  SELECT sql_id
  FROM v$sql_plan
  WHERE (object_owner, object_name)
  = (('OWNER', 'IDX_CUSTOMER_FIRST_NAME'))
  )
  ORDER BY sql_text;
  这个查询做了什么?它运行游标缓存中的所有SQL语句(V$SQL)并检查他们每一个是否在游标缓存(v$sql_plan)访问索引中存在任何执行计划元素。完成。
  当然,如果上述查询没有返回任何结果,这并不意味着没有人使用你的索引。可能还有一个非常罕见的查询,一年只会发生一次,它被游标缓存清除了。
  但是如果你将上述查询作为一个工作运行一段时间,你就可以得出这样的结论:如果这个查询不返回任何行,你的索引可能将不再需要了。
  我能发现不需要的索引吗?
  当然!运行一个类似的查询,列出没有引用V $ sql_plan表的所有引用:
  SELECT owner, index_name
  FROM all_indexes
  WHERE owner = 'OWNER'
  AND (owner, index_name) NOT IN (
  SELECT object_owner, object_name
  FROM v$sql_plan
  WHERE object_owner IS NOT NULL
  AND object_name IS NOT NULL
  )
  ORDER BY 1, 2

  同样,这并不是说你的索引将永远不会被使用,只是它们最近还没有被使用过。现在,我不会真的给你展示使用上述语句的查询,在PL/SQL循环中运行其结果和使用EXECUTE IMMEDIATE删除所有的索引,因为你可能在你的生产环境中尝试。但是,以防万一你想尝试,这里有一个提示BEGIN
  BEGIN
  FOR i IN (/* above query here */) LOOP
  EXECUTE IMMEDIATE
  'DR0P INDEX "' || i.owner || '"."' || i.index_name || '"';
  END LOOP;
  END;
  /

  但正如我说的。不要真的这样做!

  上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号