I tried optimizing them out. Nothing. Looked at the query plans - 0%. SQL server had reasonably noticed what they were and done a bang-up job handling them.
That's the infuriating thing about SQL server "advice" - it's such a black box that so many of the rules are cargo-cult stuff.
https://www.brentozar.com/blitz/blitz-result-user-defined-fu...
http://sqlblog.com/blogs/paul_white/archive/2011/12/23/forci...
Would it make more sense to have a precompiler go through and inline my UDFs? They seem pretty amenable to a macro-expansion.
1.) Don't use user defined functions in any predicate.
In order to evaluate a predicate (WHERE clause, HAVING clause, JOIN condition aka boolean comparison), the query engine needs to know what both sides of the comparison evaluate to. So for each row, it has to pull out a value out of the database, then also execute the UDF (User Defined Function) in order to answer the question "does this predicate match?". UDFs are generally going to be slower than their native equivalents, and the best suggestion is to always try to do predicate matching on pre-computed values. So if you find that you are doing a lot of UDF based predicate matching, then it may be useful to see if you can pre-calculate the value of the UDF for that row, then do the predicate matching based on the pre-computed value. In MSSQL, these columns are called "Computed Columns", and computed columns in that engine can be persistent or not. You would generally want to use the persistent type for best performance.
2.) Consider that your query needs to be able to be converted into a "search argument" to use any indexes.
At a logical level, an index is a way of sorting rows. Imagine if you take all of the books in your local library, if you have one, and sorting them in alphabetical order. If someone asks you to find all of the titles that begin with "Database", then that's pretty easy. You walk down the aisles until you find the first book that starts with the letters D, A, T, A, B, A, S, and E. Then you continue reading off the titles until you find a book that doesn't use those letters anymore. Since the books are already alphabetized, you know that you've found them all. This is the equivalent of like 'Database%'.
Now imagine that someone instead asks you to find all of the books that have the word Database anywhere in their title. That's harder. Even though the books are alphabetized, the word Database could show up anywhere in the title, not just at the beginning. So you have to read the title of every single book in order to know if it contains the word Database. This takes a lot more time. This is the equivalent of like '%Database%'.
3.) Any function you use on your values in the tables mean that there are often no indexes you can use
The scenario presented here is something like Where left(title, 4) = 'asdf' or where firstName + ' ' + lastName = '_quick_q'. Internally, the query planner is going to index use what it determines is the best based upon the left side of the predicate, and even though it might look like "left(title, 4)" would be able to use an index, and maybe in some engines it does, there is generally no index that is going to match that definition. Many times people fall into this trap with simple stuff like where UPPER(LastName) = 'Q'. It seems like the query engine could make this work, but it won't because the left hand of the predicate doesn't match the index definition.
I'm not saying there's never a good reason to use a doc DB like Mongo or a "Big Data" implementation like Hadoop, but programmers don't choose to use these things for good reasons 95% of the time. They choose to use them a) because they're new, and they want the resume points; and b) because they allow them to shed the pesky DBA and the pesky database engine, always in their hair about the "Right Way" to do things so that the data can be recalled and analyzed quickly, easily, and repeatably.
There is absolutely a flip side to this too, where DBAs behave in a massively unjustified manner toward non-DBAs.
IMO the heart of the issue is the bifurcation in roles. Both DBAs and traditional coders are programmers/developers. Both should be trained in the others' concerns and expected to help out in both parts of the system, and the role distinction of 100% DBA or 100% non-DBA should not exist. This keeps balance in the incentives on both sides.
The horrifying implications of tri-value logic and the lack of a modern type-system to allow us to have a sensible alternative to NULL is infuriating.
The bipolar attitude about how normalizing data is so important but how so much falls apart when you actually have normalized data.
How infuriatingly hard basic, sane code-reuse is. "Don't use scalar UDFs" basically screams out to me "this is a bad programming language".
Is it any wonder that developers go running to NoSQL solutions? It's not "relational algebra" that they're running from - schemaless behavior is just gravy on top of escaping dealing with the muddy, deceptive black-box world of databases.
The database takes care of everythign until it doesn't.
If you're a hobby programmer and do full-stack stuff on your own to make your dreams real, you organically stabilize on a pretty-reasonable balance between database-side accommodation and application-side accommodation. Since you have to feel the full impact of the tradeoffs made, you select the most efficient, reasonable tradeoff available in the large-scale sense.
When you introduce a hard separation between data-side and app-side responsibilities, it's just human nature to get that complexity off of your plate and onto theirs. This competition to put the burden on the other group burns bright and causes massive resentment between DBA and dev.
Unify the roles and watch this disappear. Psycho DBAs who insist on fifth normal form everywhere will gain an appreciation for data locality and consider trivial bloat in table size an acceptable tradeoff, because it will make their application-side code tasks much more tolerable. Self-important developers who treat the DBA like their personal data lackeys will gain an appreciation for good data organization and reporting facilities, because it will make their database-side management and reporting tasks much easier.
Database and application are too tightly coupled to ever successfully divorce the areas of responsibility. You just end up with people at each others' throats all the time. Merging the responsibilities (and thus the incentives) is the only way you'll get these two groups to adopt a unified perspective.