• MongoDB与SqlSugar与Ado.Net对比


    SqlSugar

    NET 4.+ & .NET CORE 高性能 轻量级 ORM框架,众多.NET框架中最容易使用的数据库访问技术

    MongoDB与MySql的安装省略...虽然遇到了一些意外的情况,也花了一些时间,但是网上大都能找到解决方法,就不赘述了。

    测试过程中使用的所有第三方库文件都可以通过Nuget获取:MySql.Data.dll,Newtonsoft.Json.dll,SqlSugar.dll,MongoDB.Driver.dll,MongoDB.Bson.dll

    本文记录,对10000条数据的插入与读取速度,来简单对比三种访问数据库的方式哪一种用起来更方便更高效,当然,这可能是片面的,但是结论不是我的目的,我的目的是为了学习了解NoSql数据库。

    考虑一下以下实体对象:Book与Tags一对多关系,要新建两张表,字段与实体对象中的属性一一对应

    public class BaseEntity
        {
            [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
            public string Guid { get; set; }
            [SugarColumn(IsIgnore = true)]
            public ObjectId id { get; set; }
        }
    public class Book : BaseEntity
        {
            /// <summary>
            /// 标题
            /// </summary>
            public string Title { get; set; }
            /// <summary>
            /// 描述
            /// </summary>
            public string Description { get; set; }
            /// <summary>
            /// 作者
            /// </summary>
            public string Author { get; set; }
            /// <summary>
            /// 价格
            /// </summary>
            public decimal Price { get; set; }
            /// <summary>
            /// 标签
            /// </summary>
            [SugarColumn(IsIgnore = true)]
            public List<Tags> Tags { get; set; }
        }
    public class Tags : BaseEntity
        {
            /// <summary>
            /// 标签
            /// </summary>
            public string Tag { get; set; }
            /// <summary>
            /// 对应的书的Id
            /// </summary>
            public string BookId { get; set; }
        }

    建了两张表,就很头疼了,插入数据的时候,要分别插入,这样的效率是比较低的。这里直接考虑用SqlSugar插入10000条数据

    private void btn_insert_mysql_Click(object sender, EventArgs e)
            {
                BookRepository db = new BookRepository();
                System.Threading.Thread thread = new System.Threading.Thread(() =>
                {
                    Stopwatch stopWatch = new Stopwatch();
                    stopWatch.Restart();
                    for (int i = 0; i < 10000; i++)
                    {
                        Book book = CreateData(i);
                        db.Insert(book);
                    }
                    stopWatch.Stop();
                    WriteLog(string.Format("SqlSugar插入Mysql 10000 条数据耗时:{0}ms", stopWatch.ElapsedMilliseconds));
                });
                thread.Start();
            }
    public void Insert(Book book)
            {
                db.Insertable<Book>(book).ExecuteCommand();
                db.Insertable<Tags>(book.Tags).ExecuteCommand();
            }

    再往MongoDB中插入10000条数据,MongoDB插入数据就很方便的了,啥都不用管,因为它的数据本来是以文档的方式存储的,一种类似于JSON对象的数据结构,叫BSON

    private void btn_insert_mongodb_Click(object sender, EventArgs e)
            {
                MongoDbHelper<Book> db = new MongoDbHelper<Book>();
                System.Threading.Thread thread = new System.Threading.Thread(() =>
                {
                    Stopwatch stopWatch = new Stopwatch();
                    stopWatch.Restart();
                    for (int i = 0; i < 10000; i++)
                    {
                        Book book = CreateData(i);
                        db.Insert(book);
                    }
                    stopWatch.Stop();
                    WriteLog(string.Format("插入MongoDB 10000 条数据耗时:{0}ms", stopWatch.ElapsedMilliseconds));
                });
                thread.Start();
            }
    public T Insert(T entity)
            {
                collection.InsertOne(entity);
                return entity;
            }

    插入数据的耗时结果对比:

    2018-09-24 13:43:05 插入MongoDB 10000 条数据耗时:3111ms

    2018-09-24 13:43:14 SqlSugar插入Mysql 10000 条数据耗时:12924ms

    数据准备好了之后,便开始测试查询。

    SqlSugar查询所有数据:

    使用sqlsugar查询数据有两种方式,一种分两次查询,这种方式最终得到的List中一共10000条数据,

    另一种,连表查询,但是会有30000条数据,且要么返回匿名对象,返回值使用dynamic接收,或者新建一个View Model,总之,需要做一些其他的工作。

    public List<Book> GetAll()
            {
                List<Book> lstBook = db.Queryable<Book>().ToList();
                foreach (var book in lstBook)
                {
                    book.Tags = db.Queryable<Tags>().Where(x => x.BookId == book.Guid).ToList();
                }
                return lstBook;
                //var lstBook = db.Queryable<Book, Tags>((bk, tg) => new object[] { JoinType.Left, bk.Guid == tg.BooksId }).Select((bk, tg) => new VBook
                //          {
                //              Guid = bk.Guid,
                //              Author = bk.Author,
                //              Title = bk.Title,
                //              Description = bk.Description,
                //              Price = bk.Price,
                //              Tag = tg.Tag
                //          }).ToList();
                //return lstBook;
            }

    Ado.Net查询:这是最原始的方式了,优势还是很明显的,写原生的sql语句,效率算是比较高了,省去了ORM解析lambda表达式,反射属性赋值等,SqlSugar是国内的开源项目,有时间的话,可以下载源代码看看。当

    然Ado.Net操作数据库不方便的地方就是DataTable转实体对象了,字段多的时候,写的头都晕了,没有技术含量却要拼命的写啊写啊写....

    下面的代码片段,查询出来有30000条数据,否则,只能查询两次,与上面使用的SqlSugar一样

    public List<Book> GetAllByAdo()
            {
                List<Book> lstBook = new List<Book>();
                string conn = "Data Source=127.0.0.1;port=3306;Initial Catalog=test;user id=test;password=123456;Charset=utf8;SslMode = none;";
                string sql = "select * from book a,tags b where a.Guid=b.BookId";
                DataTable dt = MySql.Data.MySqlClient.MySqlHelper.ExecuteDataset(conn, sql).Tables[0];
                foreach (DataRow dr in dt.Rows)
                {
                    Book book = new Book
                   {
                       Guid = dr["Guid"].ToString(),
                       Author = dr["Author"].ToString(),
                       Title = dr["Title"].ToString(),
                       Description = dr["Description"].ToString(),
                       Price = decimal.Parse(dr["Price"].ToString()),
                       Tags = new List<Tags>() { new Tags { Guid = dr["Guid1"].ToString(), BookId = dr["BooksId"].ToString(), Tag = dr["Tag"].ToString() } }
                   };
                    lstBook.Add(book);
                }
                return lstBook;
            }

    MogoDB查询数据库简直不能太方便,不用做任何的操作,直接返回实体对象

    public List<T> GetAll()
            {
                return collection.Find(_=>true).ToList();
            }
    查询结果耗时对比:
     
    2018-09-24 13:44:00 查询MongoDB 10000 条数据耗时:312ms    查询一次,10000条数据
     
    2018-09-24 13:44:14 Ado.Net查询Mysql 10000 条数据耗时:529ms    查询一次,30000条数据    没有索引
     
    2018-09-24 13:44:46 SqlSugar查询Mysql 10000 条数据耗时:26567ms    查询一次,30000条数据    没有索引
     
    2018-09-24 13:51:25 SqlSugar查询Mysql 10000 条数据耗时:87318ms    查询两次,10000条数据    没有索引
     
     
    2018-09-24 15:09:03 Ado.Net查询Mysql 10000 条数据耗时:488ms    查询一次,30000条数据 加了索引
     
    2018-09-24 15:08:14 SqlSugar查询Mysql 10000 条数据耗时:504ms    查询一次,30000条数据 加了索引
     
    2018-09-24 15:05:14 SqlSugar查询Mysql 10000 条数据耗时:4786ms    查询两次,10000条数据 加了索引
     

    对应以上结果:

    1.使用NoSql的数据库,非常的高效,非常的方便。

    2.加了索引后,对于sqlsugar查询效率提升太明显。

    3.不管是使用怎样轻量级的ORM框架,效率都是赶不上写原生sql的。

    其他代码片段:

    /// <summary>
        /// MongoDb帮助类
        /// </summary>
        public class MongoDB
        {
            private static readonly string connStr = "mongodb://127.0.0.1:27017";
            private static readonly string dbName = "test";
            private static IMongoDatabase db = null;
            private static readonly object lockHelper = new object();
            private MongoDB() { }
            public static IMongoDatabase GetDb()
            {
                if (db == null)
                {
                    lock (lockHelper)
                    {
                        if (db == null)
                        {
                            var client = new MongoClient(connStr);
                            db = client.GetDatabase(dbName);
                        }
                    }
                }
                return db;
            }
        }
        public class MongoDbHelper<T> where T : BaseEntity
        {
            private IMongoDatabase db = null;
            private IMongoCollection<T> collection = null;
            public MongoDbHelper()
            {
                this.db = MongoDB.GetDb();
                collection = db.GetCollection<T>(typeof(T).Name);
            }
            /// <summary>
            /// 新增
            /// </summary>
            /// <param name="entity"></param>
            /// <returns></returns>
            public T Insert(T entity)
            {
                collection.InsertOne(entity);
                return entity;
            }
            /// <summary>
            /// 查询所有数据
            /// </summary>
            /// <returns></returns>
            public List<T> GetAll()
            {
                return collection.Find(_=>true).ToList();
            }
        }
    View Code
    public class DbContext
        {
            string conn = "Data Source=10.101.98.197;port=3306;Initial Catalog=test;user id=test;password=123456;Charset=utf8;SslMode = none;";
            public DbContext()
            {
                db = new SqlSugarClient(new ConnectionConfig()
                {
                    ConnectionString = conn,
                    DbType = SqlSugar.DbType.MySql,
                    IsAutoCloseConnection = true
                });
            }
            public SqlSugarClient db;
        }
        public class BookRepository : DbContext
        {
            public List<Book> GetAllBooks()
            {
                List<Book> list = db.Queryable<Book>().ToList();
                return list;
            }
            public List<Tags> GetTagsByBooksId(string bookid)
            {
                return db.Queryable<Tags>().Where(x => x.BookId == bookid).ToList();
            }
            public void Insert(Book book)
            {
                db.Insertable<Book>(book).ExecuteCommand();
                db.Insertable<Tags>(book.Tags).ExecuteCommand();
            }
            public List<VBook> GetAll()
            {
                //List<Book> lstBook = db.Queryable<Book>().ToList();
                //foreach (var book in lstBook)
                //{
                //    book.Tags = db.Queryable<Tags>().Where(x => x.BookId == book.Guid).ToList();
                //}
                //return lstBook;
                var lstBook = db.Queryable<Book, Tags>((bk, tg) => new object[] { JoinType.Left, bk.Guid == tg.BookId }).Select((bk, tg) => new VBook
                          {
                              Guid = bk.Guid,
                              Author = bk.Author,
                              Title = bk.Title,
                              Description = bk.Description,
                              Price = bk.Price,
                              Tag = tg.Tag
                          }).ToList();
                return lstBook;
            }
            public List<Book> GetAllByAdo()
            {
                List<Book> lstBook = new List<Book>();
                string conn = "Data Source=127.0.0.1;port=3306;Initial Catalog=test;user id=test;password=123456;Charset=utf8;SslMode = none;";
                string sql = "select * from book a,tags b where a.Guid=b.BookId";
                DataTable dt = MySql.Data.MySqlClient.MySqlHelper.ExecuteDataset(conn, sql).Tables[0];
                foreach (DataRow dr in dt.Rows)
                {
                    Book book = new Book
                   {
                       Guid = dr["Guid"].ToString(),
                       Author = dr["Author"].ToString(),
                       Title = dr["Title"].ToString(),
                       Description = dr["Description"].ToString(),
                       Price = decimal.Parse(dr["Price"].ToString()),
                       Tags = new List<Tags>() { new Tags { Guid = dr["Guid1"].ToString(), BookId = dr["BookId"].ToString(), Tag = dr["Tag"].ToString() } }
                   };
                    lstBook.Add(book);
                }
                return lstBook;
            }
        }
    View Code

    工具:

     
    每天进步一点点.....
     
  • 相关阅读:
    超宽带技术的定位原理(转载)
    今日学习——2019年4月8日
    解答室内定位技术新方向:蓝牙AoA定位,值得了解 ——概念了解
    LED室内定位算法:RSS,TOA,AOA,TDOA(转载)
    关于值类型、引用类型以及“栈”跟“堆”的关系——转载自菜鸟教程
    华为liteos了解(一)
    物联网的概念
    c语言——字符串
    指针的操作 p*++
    在完成端口中使用GetAcceptExSockaddrs
  • 原文地址:https://www.cnblogs.com/dwBurning/p/mongodb.html
Copyright © 2020-2023  润新知