I've got a SOQL query that takes a very long time to run that's part of a larger Apex class. Below is a quick explanation of our org setup, the purpose of the query, and the query itself. Any help to optimize the query or an alternate path to get to the data would be greatly appreciated.
Sequence__c = sequences are the line items on a contract, think of it like an itemized receipt. Sequences are the child records of Contract__c records (we do not use the standard Contracts object).
Panel_Maintenance__c = Panel_Maintenance__c records represent individual panel structures which can be booked/leased by customers for specific amounts of time. Each Panel_Maintenance__c record represents a unique piece of our inventory.
Panel__c = Panel__c records represent proposed or sold bookings for a particular panel for a particular time period. Panel__c records have a lookup relationship to Panel_Maintenance__c, but are actually children of Proposal__c records. Originally Panel__c records were meant to represent proposed bookings only, but recently our Sequence Apex class was updated to insert Panel__c records to represent sold bookings. All panel records have a parent proposal record, but only some have a lookup relationship to a sequence record.
Purpose of the Query:
This query is part of an Apex class created for an Aura component which allows users to identify Panel_Maintenance__c panels that are unsold for a specific time period. Since Panel__c records are created for proposed and sold bookings, the Apex class is ultimately trying to identify records that do NOT exist. For example there could be a Panel__c record indicating a panel is booked from October 1 through October 28, and another Panel__c record indicating that same panel is booked from November 16 through December 13, but what I really care about is that there is NO Panel__c record indicating that same panel is sold between October 28 and November 16. The panel is "unsold" during that time.
This particular SOQL query takes the users office location and a start and end date entered by the user to search for SOLD panel records. After this query is complete, the Apex class stores the panels' external ids in a set, then performs a separate (not shown) SOQL query for the unique panel records in Panel_Maintenance__c for panels NOT in the sold panel id set.
To qualify as a "sold panel", the panel record must have a lookup relationship to a sequence record, and the sequence record must have a status of 'Active' or 'Expired'. Additionally, the panel's start or end date must overlap with the dates provided by the user.
SELECT Panel_ID__c, Sequence__r.Status__c, Sequence__r.Contract__c FROM Panel__c WHERE Plant_Number__c=`userdata` AND (Start_Date__c <`userinput` OR End_Date__c >`userinput`) AND Sequence__c!=Null AND (Sequence__r.Status__c ='Active' OR Sequence__r.Status__c='Expired')