简体   繁体   English

sql查询优化(oracle)

[英]sql query optimization (oracle)

It has been a while since my sql days thus I am wondering whether it is possible to further optimize the following query? 自从我的sql天以来已经有一段时间了,因此我想知道是否有可能进一步优化以下查询? The goal is to collect all accounts for each accountant including all the bookings and movements associated with it. 目标是收集每个会计师的所有帐户,包括与之关联的所有预订和变动。 Performance/query-time is very important since there are '3 digit'-million datasets... 性能/查询时间非常重要,因为有“ 3位数”百万数据集。

select Accountant.person_id, 
    Account.account_id, 
    Account.number, 
    Account.balance,
    Account_Type.type_number, 
    Booking.booking_id, 
    Booking.amount, 
    Movement.movement_date, 
    Movement.movement_desc
from Accountant
join Account on Accountant.person_id = Account.person_id
join Account_Type on Account.account_type_id = Account_Type.account_type_id
left outer join Booking on Account.account_id = Booking.account_id
left outer join Movement on Booking.movement_id = Movement.movement_id;

The entity model looks something like that: 实体模型看起来像这样: 在此处输入图片说明

UPDATE: Since some of you are wondering: Yes I am simply selecting hundreds of million of rows since the query is used to migrate data. 更新:你们当中有些人在想:是的,因为查询用于迁移数据,所以我只是选择亿万行。 The data queried is used to construct a new data structure which is put in another database... 所查询的数据用于构造新的数据结构,该数据结构被放入另一个数据库中。

  1. To allow returning accounts with no Bookings I added the outer joins. 为了允许没有预订的返回帐户,我添加了外部联接。 Is that the right syntax? 那是正确的语法吗?
  2. Here is the explain plan - seeing any optimization possibilities? 这是解释计划-看到优化的可能性了吗? 在此处输入图片说明
  3. After adding some missing indices the query takes (in an external tool) about 1/2 hour. 添加一些缺失的索引后,查询(在外部工具中)大约需要1/2小时。 In java a memory error is thrown at some point. 在Java中,有时会引发内存错误。 Any hints (except increasing memory) how to optimize that? 任何提示(增加内存除外)如何优化它?

As others have already mentioned: It is strange, you want to select hundreds of millions of records in one go. 正如其他人已经提到的:奇怪的是,您想一次性选择数亿条记录。

Aside from that: 除此之外:

  1. The left outer join on table Booking will only work, if you also outer join table Movement. 如果您还使用外部联接表Motion,则表Booking上的左侧外部联接将仅起作用。
  2. As you want all records, only full table scans (or fast full index scans for that matter) make sense. 当您需要所有记录时,只有全表扫描(或与此相关的快速全索引扫描)才有意义。 Check the explain plan if this is the case. 如果是这种情况,请检查解释计划。 (It should.) Otherwise use /*+full(tablename)*/. (应该。)否则,请使用/ * + full(tablename)* /。
  3. As you will use full table scans you may want to have them run in parallel. 由于您将使用全表扫描,因此您可能希望并行运行它们。 Check the explain plan if this is already the case. 如果已经存在,请检查解释计划。 Otherwise use /*+parallel(tablename,factor)*/. 否则,请使用/ * + parallel(tablename,factor)* /。
  4. In case the tables have many columns, it might be good to have indexes containing the desired columns, so fast full index scans instead of full table scans can be used and less disc blocks need to be read thus. 如果表中有许多列,则最好使索引包含所需的列,因此可以使用快速的全索引扫描而不是全表扫描,从而需要读取的磁盘块更少。
  5. You can reduce disc reads by compressing tables (Oracle 11g and up). 您可以通过压缩表(Oracle 11g及更高版本)来减少光盘读取。

The join syntax is clearer and recommended. 连接语法更清晰,建议使用。 I don't think you can optimise the query itself any further, but you could check the DB schema, or investigate alternatives. 我认为您无法进一步优化查询本身,但是可以检查数据库架构或研究替代方案。

DB Schema: 数据库架构:

  • are all IDs marked primary (ieindexed and clustered)? 所有ID是否都标记为主要(即索引和群集)?
  • can you check the query plans to ensure the query is being executed optimally? 您可以检查查询计划以确保查询得到最佳执行吗?

You could also consider a reporting table that is built at the end of every day (or more frequently if required) - and query from that. 您还可以考虑每天结束时建立的报告表(如果需要,可以更频繁地建立)-并从中进行查询。 Oracle supports materialised views that might help. Oracle支持可能会有所帮助的实例化视图。

Finally, a query that returns n,000,000 records really isn't much use to anyone, so you might reconsider your logic. 最后,对于任何人来说,返回n,000,000条记录的查询实际上都没有多大用处,因此您可能需要重新考虑自己的逻辑。 If you're presenting these records to a user, you need to page them (so limit the query to a page size) - or if you're presenting summary info, rewrite the query to use aggregate functions (sum/max/avg etc.) Don't use code to do what a DB does best. 如果要向用户显示这些记录,则需要分页(因此将查询限制为页面大小)-如果要显示摘要信息,则重写查询以使用聚合函数(sum / max / avg等) 。)不要使用代码来做数据库最擅长的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM