Your questions:
Is FK-index going to eat up too much space/time as table grows few million records?
No worries, here, at least not a concern "as the table grows". Both space and time requirements will grow linearly with regards to the number of records added.
(well technically not quite, if you cross boundaries that introduce an extra level in the tree, but typically a database with readily million of records, tree depth is readily where it is supposed to be)
In that case, is it worth to go for an FK-index "each time?"
Typically yes, but it is indeed a case-by-case situation. One think to consider too, rather than plain FK index are indexes that include additional columns and may be used both for searching and to cover [parts of] the select list. Again deciding on such alternative (or additional indexes) is a case-by-case, sorry ;-) ...
In what case should I NOT apply FK or Index it or do neither of it (of course I can handle a LOT from the app)
Of course all such cases, exclude ones where it is important that referential integrity be intrinsically supported by the dbms itself (Such integrity can alternatively be managed at the level of the application / processes which Insert and Delete rows in the database)
- cases when most of [time or resource] critical queries imply other filters on the table, and such that SQL can then resolve the JOIN by checking the values in the table per-se (or in a covering index, specifically, one where the FK is not the first column listed) for the [small] subset of possible results produced by these other filters.
- cases where the table table is relatively small (lookup tables and such), as SQL often decide on scan strategy for them and also as they get cached). But then, they are small, and typically relatively static, so the cost for extra indexes would not be an issue...
- there may be a few more cases...
Any other tricky to speedup JOIN or other such time-consuming lookups?
When it comes to moving the data around, for example when significant amount of data is added, etc. It is often a worthwhile strategy to drop the indexes (or some of them), do the CUD (INSERT / UPDATE / DELETE) operations, and then re-create the indexes. Of course this is not always possible, if the database is concurrently searched during the updates etc.
Also watch for the FILL_FACTOR associated with indexes, as a judicious choice for these keep the index fragmentatation to a minimum (at the cost of consuming, up from a bit more space) at least between scheduled maintenance of the indexes