I don’t think there’s any difference, performance wise.
I always use pointers.
Pointers are great.
When you use include, Parse does the main query, gathers all the ids, and then does a second query : using containedIn, which becomes $in .
The second query retrieves all the included Parse.Objects.
It’s all done automatically.
If we want to know how that works, look at your db, and look at the Adapters/Storage/Mongo folder in the parse-server source.
Pointers are stored by referencing another objects’ ID. If you are using a query such as qTable.equalTo("pointer", "some pointer");, the main performance impact would be making sure there is a index on _p_pointer
The pointer approach takes always more resources than the raw text approach. Not only does a pointer require en-/decoding resources, but also causes more data storage and traffic.
Consider this:
Field name is _p_[Class] for pointer type vs. [WhatEverYouChoose] for text type.
Field value is _[Class]$[ObjectId] for pointer type vs. [ObjectId] for text type.
Parse Server uses 9 character for object ID by default. For field value, the pointer encoding makes up >=25% of the value length, at the lower range if the class name is only 1 char like _c$123456789. For a class name Table the field value would be _Table$123456789 where it makes up 44% of the field value. Similar calculations for the field name, a string _p_[Class] compared to a single char field name u is >=400% longer, at the lower range if the class name is a single char.
For a small app, or only a few pointer fields, or an environment where you aren’t charged based on data traffic you may not really care. A convenience upside of using pointers is that Parse Dashboard allows you to navigate easily to the pointed-to object by just clicking on the pointer. Another upside is that you can easily fetch the pointed-to object in queries using Parse.Query.include.