Thanks, that makes it clearer.
So, 1-2 mil rows is definitely a big number. The row count will in any case be inefficient, even if you do it in SQL. In ThingWorx, the row count is executed after ThingWorx retrieves all those rows (as seen in your example) in memory, then it calculates the row count. It will take a bit of time to get the dataset from PostgreSQL, then storing that in-memory is a memory expensive operation, even if you do it for couple of milliseconds to calculate the row count. (Even if you do it in SQL, it will still be slow).
One way to do that is to pre-calculate based on a timer hourly count of properties, then store these in a logged property. Something like: Property1_HourlyCount. The key here is to use an interval as low as possible so that it does not impact the system when used, but at the same time allowing you to execute a count for the remainder of the interval you want also without a system impact. Eg: if you want to get the count from 09:00 to 11:45, you get the count from the Property1_HourlyCount for 09:00-10:00 and 10:00 and 11:00, then the count from 11:00 and 11:45 by executing a normal QueryPropertyHistory, that will execute far faster. Key thing here is that this method can be executed infrequently, since it still incurs a processing penalty.
In which use-case you need this row count, meaning what do you use it for?