squadbrodyaga
@squadbrodyaga
帆は風を変えた

Влияет ли тип ключа на скорость поиска по таблице?

Eсли использовать UUID вместо INT, то как это повлияет на скорость поиска по таблице?
  • Вопрос задан
  • 213 просмотров
Решения вопроса 2
mayton2019
@mayton2019
Bigdata Engineer
Да влияет потому что физический размер индекса будет больше и на 1 PAGE влезает меньше ключей такой длины. GUID индекс будет требовать больше IOPS на поиск ключа т.к. быстрее заполнится 1 и 2 уровни дерева. В то время как у 1-2-3 индекса будет еще запас по росту.
Ответ написан
Комментировать
firedragon
@firedragon
Не джун-мидл-сеньор, а трус-балбес-бывалый.
нет они только в 2 раза больше int64
ключи сортируют алгоритмы типа btree или hashmap
в общем это не заметно, но по удобству uuid уделавает инт очень сильно.

Итак погоняйте код ради интереса в среднем в 4 раза инт64 быстрее
код
using Microsoft.EntityFrameworkCore;
using System.Diagnostics;

namespace TestPerf
{
    internal class Program
    {
        static int TOTALITEMS = 400000;
        static int SELECTITEMS = 100;
        static Stopwatch _swInt= new Stopwatch();
        static Stopwatch _swGuid = new Stopwatch();
        static void Main(string[] args)
        {

            try
            {
                ConfigureDb();
                TestDb();
            }
            catch(DbUpdateException)
            {
                TestDb();
            }
            finally { 
                DropTables(); 
            }
            
        }

        private static void DropTables()
        {
            using var db = new ApplicationContext();
            db.IntTest.FromSql($"DROP TABLE IF EXISTS public.inttest;");
            db.IntTest.FromSql($"DROP TABLE IF EXISTS public.guidtest;");
            db.SaveChanges();
        }

        private static void TestDb()
        {
            var intId = new List<long>();
            var rand = new Random();
            for (int i = 0; i < SELECTITEMS; i++)
            {
                intId.Add(rand.Next(1,TOTALITEMS));
            }
            var guidId = new List<Guid>();
            using var db = new ApplicationContext();
            foreach (var id in intId)
            {
                guidId.Add(db.GuidTest.Where(x=>x.Idn == id).First().Id);
            }

           

            _swInt.Start();
            var intRes = db
                .IntTest
                .Where(x => intId.Contains(x.Id)).ToList();
            _swInt.Stop();

            _swGuid.Start();
            var guidRes = db
                .GuidTest
                .Where(x => guidId.Contains(x.Id)).ToList();
            _swGuid.Stop();
            Console.WriteLine("Int key time: " + _swInt.ElapsedMilliseconds);
            Console.WriteLine("Guid key time: " + _swGuid.ElapsedMilliseconds);
        }

        private static void ConfigureDb()
        {
            using var db = new ApplicationContext();
            for (int i = 1; i < TOTALITEMS; i++)
            {
                var it = new IntTest { Id = i };
                var gt = new GuidTest { Id = Guid.NewGuid(), Idn = i };
                db.Add(it);
                db.Add(gt);
            }
            db.SaveChanges();
        }
    }
    public class IntTest
    {
        public Int64 Id { get; set; }
    }
    public class GuidTest
    {
        public Guid Id { get; set; }
        public Int64 Idn { get; set; }
    }
    public class ApplicationContext : DbContext
    {
        public DbSet<IntTest> IntTest => Set<IntTest>();
        public DbSet<GuidTest> GuidTest => Set<GuidTest>();
        public ApplicationContext() => Database.EnsureCreated();

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseNpgsql("Server=localhost;Port=5432;Database=test;Username=test;Password=test");
        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            var builder = modelBuilder.Entity<GuidTest>();

            builder.ToTable("guidtest");
            builder.HasKey(x => x.Id);
            builder.HasIndex(x => x.Id).IsUnique();

            builder.Property(x => x.Id)
            .HasColumnName("Id")
                .HasColumnType("uuid")
                .HasDefaultValueSql("uuid_generate_v4()")
                .IsRequired();
            builder.HasIndex(x => x.Idn).IsUnique();

            var builderi = modelBuilder.Entity<IntTest>();
            builderi.ToTable("inttest");
            builderi.HasKey(x => x.Id);
            builderi.HasIndex(x => x.Id).IsUnique();

        }
    }
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы