Tag: T-SQL

  • The Cardinality Estimator in SQL Server 2014 – Going Forward and Backward

    I saw a talk from Joe Sack (b | t) on the cardinality estimator (CE) in SQL Server 2014 and found it very interesting. To be fair, some of the "how it works" isn’t something I care about much, but I did like Joe sharing some places in which you might find problems with your queries and how the cardinality estimator might affect you. The talk is worth seeing if you get the chance.

    However one of the really interesting things, and an item I appreciate Microsoft building, is a switch to turn off the new CE. Actually, it’s not turned off, but you can set it to pre-SQL Server 2014 behavior (essentially 2005-2012) or to SQL Server 2014 behavior. What’s even better is that you can set this in a number of ways.

    Setting Database Behavior for all Queries

    Turning on the new CE is as simple as setting the compatibility level to 120. This will turn on the new CE for your queries in this database.

    The flip side is setting your compatibility level to something below 120 (110, 100, etc.) and your queries will use the old CE behavior in the query optimizer.

    Setting Behavior for Queries

    You can also specifically test queries with either the new or old CE. The QUERYTRACEON option can be used with these two flags.

    • 9481 – Uses the 2012 (pre-2014) CE with queries. This is used when the database is in SQL Server 2014 (compatibility mode 120) mode.
    • 2312 – Uses the new 2014 CE when the database, or defaults, are set to use the 2012 CE.

    This is documented in KB 2801413 from Microsoft.

    Setting the Server Level

    There is a trace flag that you can use at Server startup that globally sets the CE behavior. Set 9481 at startup and your SQL Server 2014 databases will use the old CE by default. Joe documented this on his blog.

    Usage

    I think this is great because if you are concerned about workloads being effected by the CE changes, then you can set the old CE as the default and test on your real production server by executing specific queries with the new CE and the query plan.

    Alternatively, if you upgrade and find problems, you can duplicate the old CE by using a query hint and see if the query performs better.

    I’d like to see this upgrade/downgrade granularity in more features that can potentially affect performance and I would say this is a fantastic architectural win by the SQL Server development team.

  • FileTables–Inserting Directories from T-SQL

    Creating a directory in a Filetable share is easy. It looks like this:

    filetable_i

    It’s hard to see, but this was a right click, New, Folder in the share from Windows Explorer.

    However what about creating a directory from T-SQL? That’s almost as easy.

    I created that folder above by running this code:

    -- create a folder
    INSERT  INTO dbo.Explorer
            ( name, is_directory )
    VALUES  ( 'Books', 1 );

    I provided a name for my folder and then a 1 for the is_directory property. Once I ran this, the folder above appeared in my share.

    Note that this works for folders in the root, but not nested folders. I’ll tackle that in another post.

  • FileTable–Adding a file to a folder

    At my Filestream/Filetable talk yesterday at SQL Intersection, someone asked me about programmatically adding a file to a Filetable. Easy enough, I thought, since I’d seen someone do this in .NET and was thinking this has to be simple. Turns out it’s not quite so simple.

    I was assuming that I could use the GetDescendent method of the hierarchy ID for the path_locator field to get the path you needed and insert that. It turns out that’s not correct.

    I searched around when that didn’t work and found this post from Bob Beauchemin and a question on StackOverflow. If the two, Bob’s post explains things better. He actually dug into the Filetable, looking at the constraints and defaults in the schema. If you do that, you can find this constraint on the path_locator field:

    filetable_h

    The code in this constraint looks like this, which matches with what Bob and SO show as the way to calculate the path.

    ALTER TABLE [dbo].[Explorer] ADD  CONSTRAINT [DF__Explorer__path_l__6477ECF3]  
    DEFAULT (CONVERT(HIERARCHYID, '/' +     CONVERT(VARCHAR(20), CONVERT(BIGINT, SUBSTRING(CONVERT(BINARY(16), NEWID()), 1, 6))) + '.' +
         CONVERT(VARCHAR(20), CONVERT(BIGINT, SUBSTRING(CONVERT(BINARY(16), NEWID()), 7, 6))) + '.' +
         CONVERT(VARCHAR(20), CONVERT(BIGINT, SUBSTRING(CONVERT(BINARY(16), NEWID()), 13, 4))) + '/')) FOR [path_locator]
    GO

    This means that your insert statement needs to perform this calculation. For me, I decided to insert a jpg of a circle into the table, under the folder “books”. The folder looks like this:

    filetable_g

    Since I have the binary values for a circle image, I’ll use those, and then the code below. The first part of this code calculates the new path that’s needed, basing this on the path_locator value for the “Books” folder, and then building a NewID(). From there, it’s a simple insert.

    DECLARE @path HIERARCHYID
    DECLARE @new_path VARCHAR(675)
     
    SELECT  @path = path_locator
    FROM    dbo.Explorer
    WHERE   name = 'Books'
    
    SELECT  @new_path = @path.ToString()
            + CONVERT(VARCHAR(20), CONVERT(BIGINT, SUBSTRING(CONVERT(BINARY(16), NEWID()),
                                                             1, 6))) + '.'
            + CONVERT(VARCHAR(20), CONVERT(BIGINT, SUBSTRING(CONVERT(BINARY(16), NEWID()),
                                                             7, 6))) + '.'
            + CONVERT(VARCHAR(20), CONVERT(BIGINT, SUBSTRING(CONVERT(BINARY(16), NEWID()),
                                                             13, 4))) + '/'
    INSERT INTO dbo.Explorer
            ( stream_id
            , file_stream
            , name
            , path_locator
            )
    VALUES  ( NEWID()
            , 0xFFD8FFE000104A46494600010101006000600000FFE100684578696600004D4D002A000000080004011A0005000000010000003E011B0005000000010000004601280003000000010002000001310002000000120000004E00000000000000600000000100000060000000015061696E742E4E45542076332E352E313000FFDB0043000201010201010202020202020202030503030303030604040305070607070706070708090B0908080A0807070A0D0A0A0B0C0C0C0C07090E0F0D0C0E0B0C0C0CFFDB004301020202030303060303060C0807080C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108000A000D03012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00E97FE0E87FF82CA7ED35FB04FED85E09F03FC2BD6A5F87BE1097408B5C4D523D2ADAF1BC41746795248CBDC4722F970848C18940399373E43478FD75FF00827CFC68F177ED17FB0FFC2AF1D78F3461A078C7C59E19B2D4F57B110B42B14F244199846DF346AFC384392A1C024E335E95E2EF87BE1FF880968BAF687A3EB6B612F9F6C2FECA3B916F27F7D3783B5BDC60D6C5007FFFD9
            , 'Circle.jpg'
            , @new_path      
          );
    go

     

    If I now look at the folder, I see this:

    filetable_j

    An insert into the folder of a file.

    I could easily adapt this to stream in the binary values from a .NET application, or OPENROWSET, but this works well enough.

  • Is Unit Testing Important?

    This editorial was originally published on Nov 10, 2009. It is being re-run as Steve is on vacation.

    I saw a question on the SQLServerCentral ASK site the other day asking about unit testing for T-SQL stored procedures. There weren’t many responses, but they were interesting to me.

    I wondered how many people bothered to test their stored procedures as a unit. It seems that the idea of test driven development, or even of comprehensive testing of SQL code isn’t very mature. If a query runs and appears to return the data we want, do we bother to test for edge or unusual data conditions?

    Or do we even know how to write those kinds of tests?

    Testing your code as it’s being written is a well known way to reduce your technical debt and ensure better code when it’s released. It’s also a way to lower the cost of maintaining your software over its lifetime. However it slows down development as well.

    That’ s not why most people don’t test their code well. The big reason is that it’s B-O-R-I-N-G.

    But does it matter? Is there really an issue? After all most T-SQL queries are built to scale. If the data is correctly assembled into sets with a small set of data, it will work correctly on large sets of data. Maybe not efficiently, but it tends to work. So is unit testing of T-SQL code important?

    My guess is that it is not all that important. At least not as important as performance tuning. If you have extra time to spend on a query, I think most DBAs would prefer to spend it on making the SQL more efficient, not more tested.

    Steve Jones


    The Voice of the DBA Podcasts

    Everyday Jones

    The podcast feeds are available at sqlservercentral.mevio.com. Comments are definitely appreciated and wanted, and you can get feeds from there.

    You can also follow Steve Jones on Twitter:

    Overall RSS Feed: or now on iTunes!

    Today’s podcast features music by Everyday Jones. No relation, but I stumbled on to them and really like the music. Support this great duo at www.everydayjones.com.

    I really appreciate and value feedback on the podcasts. Let us know what you like, don’t like, or even send in ideas for the show. If you’d like to comment, post something here. The boss will be sure to read it.