为什么mysql分区在我的例子中没有效果

为什么mysql分区在我的例子中没有效果,mysql,partitioning,database-partitioning,Mysql,Partitioning,Database Partitioning,我尝试在Mysql中测试分区的好处 我创建了两个表:一个是分区的,另一个不是分区的 每个表中都有10万条记录 我希望用户快速查询到id列 分区表1024部分: CREATE TABLE `neworder10M_part_byuser` ( `id` int(11) NOT NULL AUTO_INCREMENT, `site_from_id` int(11) NOT NULL, `site_to_id` int(11) NOT NULL, `user_from_id` int(

我尝试在Mysql中测试分区的好处

我创建了两个表:一个是分区的,另一个不是分区的

每个表中都有10万条记录

我希望用户快速查询到id列

分区表1024部分:

CREATE TABLE `neworder10M_part_byuser` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_from_id` int(11) NOT NULL,
  `site_to_id` int(11) NOT NULL,
  `user_from_id` int(11) NOT NULL,
  `user_to_id` int(11) NOT NULL,
  `created` datetime NOT NULL,
  PRIMARY KEY (`id`,`user_to_id`),
  KEY `composite_cover` (`user_to_id`,`user_from_id`,`site_from_id`,`site_to_id`,`created`)
) ENGINE=InnoDB 
/*!50100 PARTITION BY HASH (user_to_id)
PARTITIONS 1024 */ |
具有未分区的聚集键的表:

CREATE TABLE `neworder_10M` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_from_id` int(11) NOT NULL,
  `site_to_id` int(11) NOT NULL,
  `user_from_id` int(11) NOT NULL,
  `user_to_id` int(11) NOT NULL,
  `created` datetime NOT NULL,
  PRIMARY KEY (`user_to_id`,`id`),
  UNIQUE KEY `id_UQ` (`id`)
) ENGINE=InnoDB;
当我使用python脚本对这两个表进行1000个REQ的基准测试时:

for i in xrange(1,REQS):
    user_id = random.randint(1,10000);
    cursor.execute("select * from neworder10M_part_byuser where user_to_id=%s;" % (user_id))
分区表:22卢比 未分区:22.7 RPM

为什么分区表没有速度优势?正如我所期望的,更小的数据-更快的查询

explain还显示了所使用的分区:

mysql> explain select * from neworder10M_part_byuser where user_to_id=6867;
+----+-------------+-------------------------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+
| id | select_type | table                   | partitions | type | possible_keys   | key             | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------------------------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | neworder10M_part_byuser | p723       | ref  | composite_cover | composite_cover | 4       | const | 1009 |   100.00 | Using index |
+----+-------------+-------------------------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+
但我并没有看到实际速度的提高。。。。我做错了什么

表格填写代码:

def send_orders(cur,users=10000,orders=10000000):
    for i in xrange(1,orders+1): //10000000 rows here
        print i
        from_user = random.randint(1,users)
        to_user = random.randint(1,users)
        from_site = random.randint(1,10000)
        to_site = random.randint(1,10000)
        cur.execute("INSERT INTO neworder (site_from_id, site_to_id,user_from_id, user_to_id,created)  VALUES ('%d','%d','%d','%d',NOW());" % (from_user,to_user,from_site,to_site))
mysql版本:14.14版发行版5.7.12,适用于Linux x86_64。
硬盘驱动器是ssd。

我们不希望SELECT语句在性能上有太大差异,因为查询使用的是索引范围扫描,并且分区表的查询正在修剪分区

如果不进行分区修剪,我们会期望通过对分区表进行选择来降低性能。因为这需要检查1024个索引,而不是一个索引


分区提高查询性能的想法是错误的。

这既是对问题的回答,也是对某些评论的反驳

如果WHERE子句可以导致分区修剪,那么它可以帮助提高复合索引的效率。因此,考虑到您可以选择更好的索引,与非分区表相比并没有任何优势

将分区修剪视为将BTree深度缩小1级。但是你必须做修剪。结果:几乎相同的成本。这是我对一个分区中10M行未分区与10K行范围扫描问题的回答@斯宾塞7593的答案也很好

我只发现了4个分区可以提高性能的用例。这里面有很多

按范围划分是唯一有用的分区方法。您正在使用的byhash似乎完全没有用。特别是,如果对“分区键”进行范围扫描,它必然会扫描所有分区-不可能进行“修剪”

将分区键放在任何键的第一位通常效率低下

唯一键id_UQ id-使其成为非分区测试的普通索引;这样会更有效率。它将足以处理自动增量

哎呀,@spencer7593已经说过一些这样的话,并指向我的博客。谢谢我写它是因为我厌倦了在论坛上重复我自己

您的特定查询选择。。。其中user_to_id=constant是演示任何类型的分区是多么无用的好方法。这是你真正的疑问吗?实际上,您可能还有其他一些查询可以从分区中受益;让我们看看

在较小的表缓存上快50倍?较小的表是否适合缓冲池,而较大的表是否适合缓冲池?I/O是影响性能的最大因素


如果查询中始终存在user_to_id=constant,则将user_to_id作为每个索引中的第一列,非分区表中的INDEXid除外。可以认为这相当于“修剪”。

我们不希望SELECT语句在性能上有太大差异,为什么?据我所知,通过分区键可以确定分区pXXX达O1次,然后只扫描一个已确定的分区匹配,因为它的索引包含10K行,而非分区完整数据表索引包含10M行。为什么时间扫描10K行上的索引等于10M行上的索引扫描?因为它没有对每个索引项进行完全扫描。索引的组织方式允许存储引擎非常快速地缩小可能包含它正在查找的条目的块。有了索引,就有了大量的数据块,而这些数据块中的条目是不可能存在的。这就是索引的工作方式。就查找条目而言,不需要检查的块是10000块还是10000000块并不重要。这就是性能相同的原因。不需要检查的块数是10000块还是10000000块并不重要。这就是为什么性能是sameI Mysql,我认为这是错误的说法。索引使用b+树。时间记录。我只是测试了10万行的表,在10万行的表上得到1215转/秒,而不是20转/秒。所以搜索10K行的分区比100K快得多,比10M快得多。所以事实上,我在10K上得到了一个小分区,它就像一张10M行的大桌子。它的工作速度比只有100k行的表慢约100倍!令人困惑的是,重要的是执行计划,以及这是否有效地利用了索引。完全扫描和范围扫描之间有很大的区别。我可以将显示对10K行的表的糟糕性能的测试放在一起,然后进行激烈的测试 与10米行的表格进行对比。MySQL的性能不是通过logN操作或每秒行数来衡量的。这些过度简化了正在发生的事情,而忽略了MySQL性能的实际重要性。