SQLSERVER 2008 R2 Using filtered Indexes - filtered-index

Is it true, that QUOTED_IDENTIFIER is to be set to ON when using filtered Index ?
I know it has to be so when using indexed views or index on computed columns.

Yes - from the documentation:
Required SET Options for Filtered Indexes...
SET options Required value
QUOTED_IDENTIFIER ON
If the SET options are incorrect, the following conditions can occur:
The filtered index is not created.
The Database Engine generates an error and rolls back INSERT, UPDATE, DELETE, or MERGE statements that change data in the index.
Query optimizer does not consider the index in the execution plan for any Transact-SQL statements.

Related

SQL Server FileTable Quoted Identifier error

I have a stored procedure that inserts BLOB (png images) into a SQL Server file table - like this:
...
INSERT INTO dbo.ImageContent ([name], file_stream)
VALUES ('example.png', BLOB);
...
When I execute the stored procedure, I get an error at the INSERT statement:
INSERT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations.
The thing is the stored procedure does not involve any indexed views, computed columns, filtered indexes, query notifications, XML type or spatial indexes.
Does the SQL Server file stream technology (i.e. File Table in this case) need QUOTED_IDENTIFIER to be ON? Setting it ON resolves the issue, but I'm not sure why it needs that. The documentation does not say it is needed.
Any insight? Thanks.

Is gathering statistics necessary after dropping indexes and recreating them?

I use Oracle SQL, and I have one question. I have a table with indexes and it's statistics are gathered. I have a procedure that drops the indexes, inserts data into the table, and after that recreates the same indexes again. Do I need to gather statistics again after this procedure, or will the indexes be recognized anyway?
For gathering statistics i use:
EXEC dbms_stats.gather_table_stats(''MIGBUFFER'','''||table_name||''',cascade=>TRUE);
No. There is no need to gather index statistics immediately after index creation, since Oracle automatically gathers stats for indexes at creation time.
From documentation,
Oracle Database now automatically collects statistics during index
creation and rebuild.
I think it was way back in earlier releases, when you could use COMPUTE STATISTICS clause to start or stop the collection of statistics on an index. But, now this clause has been deprecated. Oracle Database now automatically collects statistics during index creation and rebuild. This clause is supported for backward compatibility and will not cause errors.

Unable to Add Filtered Index but don't Understand Why

I am trying to update a database from a database project in Visual Studio.
The update script is generated automatically. On line 133, the script adds a filtered index.
CREATE UNIQUE NONCLUSTERED INDEX [ProgramCodes_Value]
ON [dbo].[ProgramCodes]([Value] ASC) WHERE ([IsDeleted]=(0));
But this line produces some errors:
(133,1): SQL72014: .Net SqlClient Data Provider: Msg 1935, Level 16, State 1, Line 1 Cannot create index. Object 'ProgramCodes' was created with the following SET options off: 'ANSI_NULLS'.
(133,0): SQL72045: Script execution error. The executed script:
CREATE UNIQUE NONCLUSTERED INDEX [ProgramCodes_Value]
ON [dbo].[ProgramCodes]([Value] ASC) WHERE ([IsDeleted] = (0));
An error occurred while the batch was being executed.
First off, I really don't understand the ANSI_NULLS thing. Usually, this is just a harmless warning.
Second, I can see it failed when trying to add the filtered index, but I really can't see why. Checking the data, there are no duplicates that would violate this unique index.
Can anyone point me in the right direction to understanding the problem?
From the docs:
SET ANSI_NULLS must also be ON when you are creating or changing indexes on computed columns or indexed views. If SET ANSI_NULLS is OFF, any CREATE, UPDATE, INSERT, and DELETE statements on tables with indexes on computed columns or indexed views will fail. SQL Server will return an error that lists all SET options that violate the required values. Also, when you execute a SELECT statement, if SET ANSI_NULLS is OFF, SQL Server will ignore the index values on computed columns or views and resolve the select operation as if there were no such indexes on the tables or views.

SQL Server and Persisted computed field with Hashbytes

Before changes I had a persisted computed field which used Checksum function and index to use it.
alter table Softs add TitleHash AS (CHECKSUM([Title])) PERSISTED;
All were fine until we found that Checksum produces poor hash and duplicates might occur. So we decided to use Hashbytes.
I tried both with binary result and char result
alter table Softs add TitleHashCBin AS (CONVERT(BINARY(16),hashbytes('MD4',[Title]))) PERSISTED;
or
alter table Softs add TitleHashCChar AS (CONVERT(CHAR(32),hashbytes('MD4',[Title]),2)) PERSISTED;
Unfortunately we found that a simple SELECT request does not use index for new field.
SELECT id FROM Softs WHERE TitleHashCBin = 0xC29939F6149FD65100A66AF5FD958D8B
It scans primary index which is build on Id column.
After that we created binary column, copied data from TitleHashCBin and also created index for new column.
alter table Softs add TitleHashBin AS Binary(16)
And used similar select statement.
SELECT id FROM Softs WHERE TitleHashBin = 0xC29939F6149FD65100A66AF5FD958D8B
And this one uses index by TitleHashBin field.
What a hell is going with calculated fields. Can somebody explain what I'm doing wrong or is it a bug?
P.S. Sql Server 2008 10.0.3798
Edit
I just removed char column from the table to investigate what does SSMS generate. It generated actually the same as you described.
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
--DROP INDEXes here
--GO
ALTER TABLE dbo.Softs DROP COLUMN TitleHashCChar, TitleHashChar
GO
ALTER TABLE dbo.Softs SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
So I think we can assume that table options are correct.
After that I repeated select statements but with the same execution plan as before...
Edit
I resolved to task using simple binary fields and Insert/Update triggers to update them. Works like a charm. But it is still unclear why it has so strange behavior?..
Make sure your set options are correct, from BOL Link
SET Option Requirements
The ANSI_NULLS connection-level option must be set to ON when the CREATE TABLE or ALTER TABLE statement that defines the computed column is executed. The OBJECTPROPERTY function reports whether the option is on through the IsAnsiNullsOn property.
The connection on which the index is created, and all connections trying INSERT, UPDATE, or DELETE statements that will change values in the index, must have six SET options set to ON and one option set to OFF. The optimizer ignores an index on a computed column for any SELECT statement executed by a connection that does not have these same option settings.
The NUMERIC_ROUNDABORT option must be set to OFF, and the following options must be set to ON:
ANSI_NULLS
ANSI_PADDING
ANSI_WARNINGS
ARITHABORT
CONCAT_NULL_YIELDS_NULL
QUOTED_IDENTIFIER
Setting ANSI_WARNINGS to ON implicitly sets ARITHABORT to ON when the database compatibility level is set to 90. If the database compatibility level is set to 80 or earlier, the ARITHABORT option must explicitly be set to ON. For more information, see SET Options That Affect Results.

SQL Server: Compare Index Performance

How can I compare the performance of an Index on a table using the Query Analyzer?
I would like to run the same query through the Estimated Execution Plan twice, once using the index and once without, and have a good comparison of the table scans/index scans that are generated.
I have tried CREATE INDEX..., SELECT..., DROP INDEX..., SELECT. I expect the first query to use the index and the second to have no index, but both execution plans will use the index.
If there is no index, then it can't be used. However, the index still exists for the estimated execution plan for the 2nd select, so it is evaluated. The DROP INDEX plan is also just an estimate too
I'd use the actual execution plan anyway, because personally I don't like the estimated one.
You can use SET SHOWPLAN TEXT to capture what is actually used in the query window (or use the graphical one). I'd also use SET STATISTICS IO and often SET STATISTICS TIME too.
Use the Sql Server Profiler under configuration tools. Run your queries with and without indexing and record the data reads / writes timing etc of your function calls. This should give you a clear idea if your indexes have improved performance (less reads / latency etc.)
use this at the beginning of the query window. it'll clear any plan caches.
dbcc freeproccache
go
dbcc dropcleanbuffers
go
so have that at the top, and then put your dreat and drop index code in a comment, and then your query. run it initially without an index and see what it looks like, then create the index and rerun it.
and yes, use the actual execution plan and you can also use client statistics.
The technique that ended up working for me was to use the WITH keyword in the FROM clause.
When the index is created:
SELECT * FROM table WHERE ...
SELECT * FROM table WITH (INDEX(0)) WHERE ...
The first query will (probably) use the index, the second will not.
You could also use multiple indexes like:
SELECT * FROM table WITH (INDEX(IX_test1)) WHERE ...
SELECT * FROM table WITH (INDEX(IX_test2)) WHERE ...