首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL Insert Performance stressTool

MySQL Insert Performance stressTool
EN

Stack Overflow用户
提问于 2012-01-13 23:44:19
回答 2查看 675关注 0票数 1

*如果你懒于阅读描述,你可以在最后找到我的问题……

嗨,我建立了一个简单的数据库:

代码语言:javascript
复制
CREATE TABLE `users` (
  `id` varchar(45) NOT NULL,
  `full_name` varchar(45) NOT NULL,
  `first_name` varchar(45) NOT NULL,
  `last_nmae` varchar(45) NOT NULL,
  `login` varchar(45) NOT NULL,
  `password` varchar(45) NOT NULL,
  PRIMARY KEY (`id`,`full_name`,`login`),
  UNIQUE KEY `idusers_UNIQUE` (`id`),
  UNIQUE KEY `login_UNIQUE` (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

现在我正在测试插入单行的性能。

我用C#创建了一个压力工具,并将其运行到1M行。如果你感兴趣,这是代码:

代码语言:javascript
复制
abstract class Job
    {
        private static object synObject = new object();
        private static int _id = 0;
        private static DateTime startingTime = DateTime.Now;
        private const int JOB_PER_SIRCLE = 10;

        protected int id;
        public Job()
        {
            lock (synObject)
            {
                _id++;
                id = _id;
            }
        }

        public void run()
        {
            while (true)
            {
                for (int i = 0; i < JOB_PER_SIRCLE; i++)
                {
                    doJob();
                }
                lock (synObject)
                {
                    calculate();
                }
            }
        }

        private static DateTime lastLog = DateTime.Now;
        private static long numOfJobsAcomplished = 0;
        private static long totalNumOfJobsAcomplished = 0;

        private static void calculate()
        {
            totalNumOfJobsAcomplished += JOB_PER_SIRCLE;
            numOfJobsAcomplished += JOB_PER_SIRCLE;
            DateTime now = DateTime.Now;
            TimeSpan timePass = now - lastLog;

            if (timePass.TotalSeconds > 1)
            {
                double total = 1000000;
                TimeSpan speed = TimeSpan.FromMilliseconds(timePass.TotalMilliseconds / numOfJobsAcomplished * total);
                Console.WriteLine("Speed = " + String.Format("{0:00.0000}", speed.TotalMinutes) + " Completed " + String.Format("{0:00.000}", totalNumOfJobsAcomplished / total * 100) + "% time pass " + (now - startingTime));
                lastLog = now;
                numOfJobsAcomplished = 0;
            }
        }

        protected abstract void doJob();
    }

在doJob()方法中,我执行插入操作,运行16个作业,16个线程(我发现这是我的机器上的最佳性能)。

无论如何,我的问题是关于结果,我花了85到105分钟来插入1,000,000行。这是快速的,还是我应该寻找不同的数据库来使用?

附注*当我插入时,我也使用MD5Crypt算法进行散列

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-14 00:06:26

当有人试图将编写速度归咎于软件而不考虑其他因素时,我总是觉得很有趣。那么,让我们开始吧。

MySQL有两个广泛使用的引擎。MyISAM和InnoDB。InnoDB是一个事务引擎,它使用聚集的主键将记录写到硬盘上。这意味着它进行各种计算,以便安全地将数据写入磁盘,并使顺序记录彼此相邻地写入。这意味着使用主键查找很快,但需要一段时间才能写下来。

将此转换为简单的英语,这意味着您的计算机将稍微更加努力地将数据以物理方式安全地写入到disk 中,并以这样一种方式快速找到记录。

这也意味着整个磨难中的瓶颈是你的硬盘。85分钟后插入1毫升。记录大约是每秒200次插入。对于一个普通的7200转/分的机械驱动器来说,这是一个相当不错的数字(我的驱动器可以达到350左右的IOPS)。因此,在350 IOPS (以我的驱动器为例)中,您达到了200,这是一个很好的数字,因为您的HDD用于读写,并且您的操作系统可能运行了几个需要HDD I/O的服务。

DR-如果你使用不同的软件,一开始写起来会稍微快一点。在更换软件之前,您需要考虑所有因素。

票数 1
EN

Stack Overflow用户

发布于 2012-01-15 01:07:51

如果你想优化你的插入性能,我建议你把你的主键改为合成的自动增量bigint。原因是Innodb在主键上使用聚集索引,该索引按范围存储键。如果您使用非顺序主键,那么在最坏的情况下,您将需要读取内存块并将其写回每一行,而不是像使用顺序键那样使用缓存。当您插入顺序键时,性能会增加几个数量级,请尝试一下。

代码语言:javascript
复制
CREATE TABLE `users` (
  `id` bigint(20) auto increment not null PRIMARY KEY,
  `user_id` varchar(45) NOT NULL,
  `full_name` varchar(45) NOT NULL,
  `first_name` varchar(45) NOT NULL,
  `last_nmae` varchar(45) NOT NULL,
  `login` varchar(45) NOT NULL,
  `password` varchar(45) NOT NULL,
  UNIQUE KEY (`user_id`,`full_name`,`login`),
  UNIQUE KEY `idusers_UNIQUE` (`user_id`),
  UNIQUE KEY `login_UNIQUE` (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

顺便说一句,我不确定之前的id(user_id)是什么,所以我留下了,但是如果你使用它作为合成主键,你可以把它去掉。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8853158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档