Question

I'm out of ideas, so I'm asking for your help. I have a weird problem which I cannot find a cause for no matter how much I search on the internet.

Thing is, I have two laptops:

l1 : HDD and a Kingston HyperX Fury SATA-III SSD (240G)

l2 : HDD and a Samsung 960 evo, nvme SSD (500G)

And I have a procedure to test the performance of the database, which inserts, selects and deletes from 3 different tables, in numbers of 10,000 and 100,000.

l2 was bought after l1 and I tried to migrate everything I had on l1 to l2, including the databases. After running the performance procedure I noticed something weird, l2 was taking way more than l1 was taking. An example being the insertion of 10,000 lines in a table, l1 would take 1 second, where l2 would take 28 seconds. Of course I didn't have the patience to try the 100,000 insertions on l2, where on l1 would take only 40 seconds.

So, I tried to find the root of the cause. Opened task manager (I'm using Windows 10), performance tab and found out that, when it's about to insert, the SSD is writing only with 200kb/s, whereas l1's SSD writes with 4.4MB/s.

l2

enter image description here

Of course, I took the possibility that the SSD might be defected so I used 3 benchmarks to see. First one I used was Samsung Magician, CrystalDiskMark and AS SSD Benchmark. All of those 3 benchmarks said there is no problem and my SSD is working at the speed it should be working. I have to note that all my drivers are up to date and the firmware of the ssd is the latest one. I tried reinstalling the SQL Server, I tried changing the editions from Enterprise to Developer (Developer being the one I use on l1).

Another thing I tried was, detaching the database. moving it to the other drive and attaching it back. To find out that, it works better than on the ssd.

The results for each performance check (10,000 inserts + select + delete): (IncepeLa = StartsAt, SeIncheieLa = EndsAt)

l2 on SSD: enter image description here

l2 on HDD: enter image description here

l1 on SSD: enter image description here

In the end, the question is... Why does SQL Server perform significantly worse on a piece that is supposed to be superior to an HDD?

Edit:

enter image description here

Edit 2:

I added another image that shows an interesting thing regarding the stall time. enter image description here

Ugly code:

declare @id_test int
declare @name_test nvarchar(50)

declare ctest cursor
for
    select CodTest, Nume from Teste;
open ctest
    fetch next from ctest into @id_test, @name_test;
    while @@FETCH_STATUS = 0 begin
        if @name_test = 'insert'
        -- @name_test TesteTabele
        begin
            declare @t_t_cte int
            declare @t_t_cta int
            declare @t_t_nr int
            declare @t_t_p int

            insert into RulariTeste (Descriere, IncepeLa, SeIncheieLa) values ('Add in table', SYSDATETIME(), null);
            declare c_t_t cursor
            for
                select * from TesteTabele
            open c_t_t
                fetch next from c_t_t into @t_t_cte, @t_t_cta, @t_t_nr, @t_t_p
                while @@FETCH_STATUS = 0 begin
                    insert into RulariTesteTabele (CodRulareTest, CodTabel, IncepeLa, SeIncheieLa) values (@t_t_cte, @t_t_cta, SYSDATETIME(), 0);
                    exec('addfields' + @t_t_cta + ' ' + @t_t_nr);
                    update RulariTesteTabele set SeIncheieLa = SYSDATETIME() where CodRulareTest = @t_t_cte and CodTabel = @t_t_cta;
                    fetch next from c_t_t into @t_t_cte, @t_t_cta, @t_t_nr, @t_t_p
                end
            close c_t_t
            deallocate c_t_t
            update RulariTeste set SeIncheieLa = SYSDATETIME() where @id_test = CodRulareTest;
        end
        else if @name_test = 'select'
        -- @name_test TesteViewuri
        begin
            declare @t_v_ct int
            declare @t_v_cv int

            insert into RulariTeste (Descriere, IncepeLa, SeIncheieLa) values ('Select view', SYSDATETIME(), null);
            declare c_t_v cursor
            for
                select * from TesteViewuri
            open c_t_v
                fetch next from c_t_v into @t_v_ct, @t_v_cv
                while @@FETCH_STATUS = 0 begin
                    insert into RulariTesteViewuri (CodRulareTest, CodView, IncepeLa, SeIncheieLa) values (@t_v_ct, @t_v_cv, SYSDATETIME(), 0);
                    select * from (select Nume from Viewuri where CodView = @t_v_cv) as aview;
                    update RulariTesteViewuri set SeIncheieLa = SYSDATETIME() where CodRulareTest = @t_v_ct and CodView = @t_v_cv;
                    fetch next from c_t_v into @t_v_ct, @t_v_cv
                end
            close c_t_v
            deallocate c_t_v
            update RulariTeste set SeIncheieLa = SYSDATETIME() where @id_test = CodRulareTest;
        end
        else if @name_test = 'delete'
        begin
            insert into RulariTeste (Descriere, IncepeLa, SeIncheieLa) values ('Delete from table', SYSDATETIME(), null);
            delete from topic_follows;
            delete from topics;
            delete from users;
            update RulariTeste set SeIncheieLa = SYSDATETIME() where CodRulareTest = (select TOP(1) CodRulareTest from RulariTeste order by CodRulareTest desc);
        end
        fetch next from ctest into @id_test, @name_test
    end
close ctest;
deallocate ctest;

The addfields functions are supposed to add fields for the tables, with a while.

Edit 3: To make matters more clear, it's not about the algorithm used. I'll demonstrate by making a while in which I add 10,000 values. Once when the db is on the SSD and once when the db is on the HDD, I'll use only l2 for this test.

An image consisting of both, because it's the last one I can post (I don't have 10 reputation to post more than 8 images) enter image description here

As it can be noticed, when the db is on the HDD it executes the inserts in 2 seconds, whereas when it's on the SSD it inserts them in 27 seconds.

Was it helpful?

Solution 2

Okay, I solved it. After searching around and trying lots of different stuff it finally came to an end.

I wrote in the original question that "all my drivers are up to date", which, looks like it was a jerk lie coming from me. I apologize for that, I updated only the firmware and had visions of updating the driver as well.

Seems like everything was solved by installing the latest driver from the original site of Samsung. IMHO I didn't expect such drastic changes over a driver change.

The driver I had before was, as shown in the tool "Samsung Magician" under the NVMe Driver, owned by Microsoft. After installing the Driver, it shows Samsung.

I again apologize for the misinformation, and I thank Brent Ozar for the support, which without, I would've long abandoned this quest and would've just "dealt with it".

OTHER TIPS

Whenever you've got a performance problem, start by asking, "What's my top wait type?" Wait stats tell you what SQL Server is waiting on.

I like measuring waits with sp_BlitzFirst (disclaimer: I wrote it.) It's a free, open source, MIT licensed script that you can call to take a sample of your waits, like this:

EXEC sp_BlitzFirst @Seconds = 60, @ExpertMode = 1;

That'll take a 60-second sample of your waits. Post a screenshot of the wait stats section, and we may be able to explain what the server is waiting on.

Update: your added screenshot shows 2 seconds of WRITELOG waits in the span of 60 seconds. Basically, your SQL Server just isn't waiting that much. My guess is that your simulated workload involves serial singleton activity: working on one row at a time, from just one thread in a load generation tool. That's not a great way to simulate workloads - you'll want to use a multi-threaded load generation tool, with lots of activity happening at once, and doing more than one row of activity at a time.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top