In practical applications, you often need to speed up the optimization. Advanced decomposition methods add an extra layer of complexity to your code that needs to be maintained and kept bug-free. I, therefore, likes to avoid them to keep the code and model simple.
Here are some methods I like to use. Some of them have the downside that you won't necessarily find the optimal solution, but if you benchmark your different models you can get a good sense about the trade-offs between running time and solution quality.
Simplify the model
Identify which constraints or objectives that contribute the most to the high solution time. Often a small part of the model can have a huge impact. Try to see if the parts of the model really are necessary for the solutions to be useful. Talk to the end-users and see if there are other ways they could be formulated that would make it easier to solve.
Reduce the solution space
You will often have solutions that are very unlikely because they are expensive or have some bad features that makes them hard to use in practice. You can fix variables to zero that likely would result in bad solutions, or add some additional constraints to remove solutions that wouldn't be practical.
This is an easy one. Often you will have an existing solution that is almost feasible or just bad quality. Feed it into the solver as a start solution will usually give significant speed improvements.
MIP solvers are built to solve a large variety of different models. You can often get significant speed ups by tuning the parameters to your specific model. Both CPLEX and Gurobi have parameter tunning tools that can help you find better parameters.
If you have multiple levels of decisions. You can start by solving the most important decisions and fix those before you solve for the rest of the decisions.
A good example is this article by Lach and Lübbecke (2012) where they solve a timetabling problem by first assigning the times for courses and then assign the rooms.
You can also use the MIP solver as part of a local search. If you have a start solution you can fix a part of the variables and solve the resulting smaller problem. You can then fix a different part of the variables and continue like this.
An example of this used to solve a timetabling problem can be seen in this paper by Lindahl et al. (2018).
 Lach, G., Lübbecke, M. (2012). Curriculum based course timetabling: New solutions to Udine benchmark instances. Annals of Operations Research. 194:255-272.
 Lindahl, M., Sørensen, M., Stidsen, T. R. (2018). A fix-and-optimize matheuristic for university timetabling. Journal of Heuristics. 24(4):645-665.