Indices for a join query with datetime range
For this specific query, I would create indexes on patients(practice_id, species) and transactions(patient_data_id, practice_id, transaction_date) and then rewrite the query as follows:

select count(distinct p.id)
from patients p
where p.practice_id = 6 and p.species = 'canine'
    and exists (select 1 
                from transactions 
                where patient_data_id = p.patient_data_id 
                and practice_id = 6 
                and transaction_date BETWEEN '2015-01-01' AND '2015-12-31')


The database won't go through all the transactions but will stop once it finds the first transaction that meets the conditions, as that's all you need to find out the final result (basically, patients that have at least one transaction). I also removed the first distinct as you don't need it - count will return only one row.