Missriktad prestandaoptimering

2012-12-20

    Jag hittade lite kod ute hos kunden som jag inte kan låta bli att kommentera. Fältet activated är en bit i databasen och koden kommer att köras ganska ofta. Koden ligger i en CLR-lagrad procedur, men kommentarerna hade gällt även om det var en fristående process.

    Hittad kod: queryStatementSB.Append("select "); queryStatementSB.Append("value "); queryStatementSB.Append("from TheTable "); queryStatementSB.Append("where activated='True' AND tag='"); queryStatementSB.Append(paramName); queryStatementSB.Append("'");

    Mitt förslag: string sql = "select value from TheTable where activated=1 AND tag=@paramName";

    Jag hade tänkt strunta i säkerhetsaspekten, men eftersom sammanslagna strängar i sql-sammanhang lämnar en sur eftersmak kan jag inte låta bli att länka lite:

    Koden är lite ryckt ur sitt sammanhang, men enda anledningen jag kan se till att använda en StringBuilder är för att man inte vill ödsla cpu-cykler på att slå ihop statiska strängar.

    Det är dock lite ogort arbete när man sedan stoppar in en sträng som värde till activated. Jag missänker att utvecklaren trodde att en bit i sql är samma sak som en bool i C# och försökte med värdet True först, för att sedan sätta fnuttar runt och få igenom koden. En bit är 1 eller 0, ‘True’ kommer leda till en onödig typkonvertering.

    Den sammanslagna strängen kommer dessutom vara prestandahämmande i sql-servern när den väl körs. SQL Server försöker lagra query plans och återanvända dem om samma fråga ställs flera gånger. Det kluriga är att parametrar inte är en del av det som sparas för att identifiera frågan. SQL Server skapar helt enkelt en hash av SQL-uttrycket och använder den som nyckel till en kompilerad query plan.

    Vad har jag missat?