Sql Server : Lower function on Indexed Column - sql

I found one big issue.
I have added the Lower function to indexed column of one of the table to fetch the data.
The table contains more than 100K records.
While fetching the records, the cpu usage goes to 100%.
I could not understand, how this much drastic change can happen just because of Lower() function.
Please Help!

What you could do, if you really need this query a lot, is create a persisted computed column that uses the LOWER() function. Index that column and you should be fine again:
ALTER TABLE dbo.YourTableName
ADD LowerFieldName AS LOWER(YourFieldName) PERSISTED
CREATE NONCLUSTERED INDEX IX_YourTableName_LowerFieldName
ON dbo.YourTableName(YourFieldName)
That would keep a lower-case representation of your field in your table, it's always up to date, and since it's persisted, it's part of your table and doesn't incur the penalty of the LOWER() function. Put an index on it and your search should be as fast as it was before.
Links:
MSDN docs on SQL Server 2008 computed columns
Complex Computed Columns
Using Computed Columns in SQL Server with Persisted Values
Top 10 Hidden Gems in SQL Server 2005 - persisted computed columns are item #3
SQL Server Computed Columns
Working with computed columns

When you add LOWER() (or any function) around a column it is no longer possible to use an index (it is no longer SARG-able).
By default, SQL Server is not case sensitive, so you should be able to remove it.

I believe SQL Server is not case sensitive, so should remove it the Lower function, It should behave normally.

Related

How to avoid function in the left field side of the predicate?

As per this article,
First Rule: You can’t use a function in the left side (the field side) of the predicate.
I have a table with a field TOTAL_ARREARS declared as
[TOTAL_ARREARS] [nvarchar](50) NULL
and I cannot change that.
Now the query is a simple one
select Id,name
from tbl
where CAST(TOTAL_ARREARS AS FLOAT)> 0
The execution plan shows
How can I apply the First Rule of the article here (avoiding function on the left)?
Edit
I tried with WHERE TOTAL_ARREARS NOT IN('0.000','.000') that though solved but not happy with the solution.
Is there anything better?
First of the table design should be looked into where we are using a varchar column to store numeric values.
In case of Oracle database you can always explore the option of function based index to get around of these kind of issues. In case of function based indexes the index key will be based on functions rather than the actual column value. It will only be used when you use the same exactly the same string(including case of letters) in the predicate.
In case of databases where function based index is not available you can consider creating an additional column as mentioned in the following post for sql server.
Function-based indexes in SQL Server

PERSISTED Computed Column vs. Regular Column

I have a high performance DB (on SQL Server 2012). One of my views had a virtual column represented by an inline scalar valued UDF computing custom hash from the previous column value. I moved this calculation from the view into one of the underlying tables to improve the performance. I added a new computed column to the table and persisted the data. Then, created index on this column and referenced it back in the corresponding view (basically migrating the logic from the view into the table).
Now I am wondering why wouldn't I just add a regular VARCHAR(32) column to the table instead of the computed PERSISTED column? I could create a DEFAULT on this column with the above mentioned UDF for all new inserts and recalculate the historical records.
Is there any advantage of the indexed computed column with PERSISTED data vs. regular NC indexed column?
Thx.
The computed column will keep your field up to date if the field data it is based on is changed. Adding just a default will update the field on insert if no value is provided for the field.
If you know that your data is not going to change (which i think you are implying but did not specify in your question), then they are functionally the same for you. The computed column would probably be preferred though to prevent accidental update of the field with an incorrect value (bypassing the default). Also it is clear to any other developers what the field is to be used for.
You could switch to a "normal" column with a default value or insert trigger. The one potential issue is that unlike a computed column anyone with insert/update access could (potentially accidentally) change the value of the column.
Performance is going to be the same either way. In essence that is what the db is doing behind the scenes with a persisted computed column. As a developer a column that is persisted computed is clearer in the intent than a default value. Default value implies it is one of many possible values not the only possible value.
Be sure to declare the UDF With SchemaBinding. This will allow SQL Server to determine if the function is deterministic and flag it as so. That can improve query plan optimization in some cases.
There is no performance difference. However, in terms of database design it is more elegant when you have your pre-calculated column in the persisted view.

Is it possible to column partitioning in SQL Server

The size of each record of table is a performance parameter. that means if size of record was small SQL Server fetch more records in each read from physical hard.
In most of our queries we not use all column of table, and may be some column use only in specific query. Is it possible for we partitioning columns of each table to have better performance.
I use SQL Server 2008 R2.
Thank you.
True column level partitioning comes with column oriented storage, see Inside the SQL Server 2012 Columnstore Indexes, but that is available only in SQL Server 2012 and addresses specific BI workloads, not general SQL Server apps.
In row oriented storage the vertical partitioning is actually another name for designing proper covering indexes. If the engine has an alternative narrow index it will use it instead of the base table, when possible.
The last alternative, manually splinting the table and joining the vertical 'shards' in queries (or defining joining views, same thing) is usually ill advised and seldom pays off.
At the moment with SQL Server 2008, you cannot partition tables horizontally. If you have a large number of columns, you would need to chop it into horizontal chunk tables that share a common key and then skin them with an update-able view to give the illusion of one very wide table.
If there are just a few large columns (e.g. VARCHAR(1000)), you can normalize your data into unique value tables.
The one exception to the no column partitioning rule are character columns declared as max (varchar(max), for example).
These are stored on a separate data page. I believe this page is not read in unless the column is referenced in the query. If I am wrong, I'am sure more knowledge people will correct me.

Computed columns or store

I need a couple of computed columns that contain count totals (indexed columns). Do you think it is better to use a computed column in a view or add extra columns to the table that will store the totals? Adding extra columns would probably mean using triggers to keep the count totals correct.
DB is MS SQL 2008 R2.
You can use a indexed view to get the performance of stored columns at no maintenance effort.
It depends.
If the tables change a lot but you rarely need the counts, a view is better. The question "view vs. computed columns" is one of DB design. If you can't change the original table or the DBMS doesn't support computed columns, use a view. If you can change the table definition, computed columns can be better but they also clutter the definition and make select * slower if you don't always need this data.
If the table rarely changes but you need those numbers a lot, use extra columns with triggers to avoid performance problems.

Optimal Sybase ASE Table Locking Scheme a for Reference Code Table

I have a reference code table that will only be read from during normal use, and it aught to be only updated for product changes (monthly).
What table locking should I be using in the create table statement?
I was assuming ALLPAGES because that keeps the total number of read locks down that ASE needs to manage; but I am getting different 'advice' from another developer on the project.
I see other reference tables in the DB in question that use ALLPAGES; but they were upgraded from 12.5 it just may be a holdover from what was available then.
The table isn't very wide, it has two numeric code id columns, a char(1) column, and is clustered on the two numeric codes.
I have only obvious answer - run sp_object_stats at the first and choose locking scheme.
If the reference table is only for reading, All-Pages locking is best as it takes least number of locks ( that you said ) and there is no conflict on Shared Locks that the processes acquire while reading data.
Just to give you an additional tip on performance: Always try to use a reference table through a co-related sub-query to take the advantage of sub-query caching. Also remember that sub-query caching takes place only when the sub-query has not been flattened by the optimizer and not converted back into a regular join. The trick to ensure than sub-query is not flattened is to use an aggregate function say max(attr) on the attribute. The max function will just be dummy without any "Group By".