Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php MySQL数据库行数优化_Php_Mysql_Database_Innodb_Myisam - Fatal编程技术网

Php MySQL数据库行数优化

Php MySQL数据库行数优化,php,mysql,database,innodb,myisam,Php,Mysql,Database,Innodb,Myisam,我有一个MySQL 5.6.26数据库,数据量很大,我在表连接上的计数选择有问题 执行此查询大约需要23秒: SELECT COUNT(0) FROM user LEFT JOIN blog_user ON blog_user.id_user = user.id WHERE email IS NOT NULL AND blog_user.id_blog = 1 表user是MyISAM,包含id、电子邮件、名称等用户数据 CREATE TABLE `user` ( `id` int(11)

我有一个MySQL 5.6.26数据库,数据量很大,我在表连接上的计数选择有问题

执行此查询大约需要23秒:

SELECT COUNT(0) FROM user
LEFT JOIN blog_user ON blog_user.id_user = user.id
WHERE email IS NOT NULL
AND blog_user.id_blog = 1
表user是MyISAM,包含id、电子邮件、名称等用户数据

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) DEFAULT NULL,
  `email` varchar(100) DEFAULT '',
  `hash` varchar(100) DEFAULT NULL,
  `last_login` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`) USING BTREE,
  UNIQUE KEY `email` (`email`) USING BTREE,
  UNIQUE KEY `hash` (`hash`) USING BTREE,
  FULLTEXT KEY `email_full_text` (`email`)
) ENGINE=MyISAM AUTO_INCREMENT=5728203 DEFAULT CHARSET=utf8
表blog_user是InnoDB,只包含id,id_user和id_blog user可以访问多个blog。id是主键,id_blog、id_user和id_blog-id_user上都有索引

CREATE TABLE `blog_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_blog` int(11) NOT NULL DEFAULT '0',
  `id_user` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_blog_user` (`id_blog`,`id_user`) USING BTREE,
  KEY `id_user` (`id_user`) USING BTREE,
  KEY `id_blog` (`id_blog`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5250695 DEFAULT CHARSET=utf8
我删除了所有其他表,并且没有其他连接到MySQL服务器测试环境

到目前为止,我发现:

当我从用户表中删除一些列时,查询的持续时间会缩短,就像每个删除的列缩短2秒一样 当我从用户表中删除除id和电子邮件之外的所有列时,查询的持续时间为0.6秒。 当我将blog_user表也更改为MyISAM时,查询的持续时间为46秒。 当我将用户表更改为InnoDB时,查询的持续时间为0.1秒。
问题是为什么MyISAM执行命令如此缓慢?

首先,在对查询稍加修改后,对其进行一些评论:

SELECT COUNT(*)
FROM user u LEFT JOIN
     blog_user bu
     ON bu.id_user = u.id
WHERE u.email IS NOT NULL AND bu.id_blog = 1;
表别名有助于更轻松地编写和读取查询。更重要的是,您有一个左连接,但您的WHERE子句正在将其转换为一个内部连接。所以,这样写:

SELECT COUNT(*)
FROM user u INNER JOIN
     blog_user bu
    ON bu.id_user = u.id
WHERE u.email IS NOT NULL AND bu.id_blog = 1;
差异很重要,因为它影响优化器可以做出的选择

接下来,索引将有助于此查询。我猜blog\u userid\u blog、id\u user和userid、email是最好的索引


列数影响原始查询的原因是它执行了大量I/O操作。列数越少,存储记录所需的页面就越少,查询运行得越快。适当的索引应该工作得更好、更一致。

要回答为什么myisam比InnoDB慢的真正问题,我不能给出权威的答案

但这肯定与两个存储引擎之间的一个更重要的区别有关:InnoDB确实支持外键,而myisam不支持外键。外键对于连接表很重要

我不知道定义外键约束是否会进一步提高速度,但可以肯定的是,它将保证数据的一致性


另一个注意事项:您注意到,删除列时,时间会缩短。这表示查询需要进行完整的表扫描。这可以通过在电子邮件列上创建索引来避免。user.id和blog.id\u用户可能已经有了索引,如果没有,这是一个错误。参与外键(显式或非显式)的列必须始终具有索引

事件发生后很长一段时间,OP都会用到这一点,前面所有加快查询速度的建议都是完全恰当的,但我想知道为什么没有人对EXPLAIN的输出发表评论。具体地说,选择电子邮件索引的原因以及它与用户表中电子邮件列的定义的关系

优化器选择了电子邮件列上的索引,可能是因为它包含在where子句中。这个索引的key_len相对较长,并且它是一个相当大的表,给定了auto_increment值,因此这个索引的内存需求将远远大于它选择id列4字节和303字节时的内存需求。电子邮件列可以为NULL,但默认值为空字符串,因此,除非应用程序显式设置NULL,否则您无论如何都不会在该列中找到任何NULL。在给定唯一约束的情况下,也不会找到多个默认记录。列默认值和唯一约束似乎完全不一致

考虑到上述情况,以及我们只需要查询中的计数这一事实,我想知道where子句的email部分除了在将每个值与NULL进行比较时减慢查询速度之外是否还有其他用途。如果没有它,优化器可能会选择主键并做得更好。更好的方法是完全忽略用户表,并根据Gordon Linoff突出显示的blog_用户的覆盖索引进行计数

这里还有另一个值得一提的索引问题:

在用户表上

 UNIQUE KEY `id` (`id`) USING BTREE,

是多余的,因为id是主键,因此定义上是唯一的。

要回答上一个问题, 问题是为什么MyISAM执行命令如此缓慢? MyISAM取决于硬盘的速度,
一旦数据被读取,INNODB将以RAM的速度运行。第一次运行查询可能会加载数据,第二次和以后将避免硬盘驱动器,直到内存耗尽。

如果可能,使用索引和内部连接您是否使用了查询解释,以查看它是否能让您知道它在哪里花费时间?MyISAM必须从磁盘读取所有数据,检查每一行并将其添加到计数中。据我所知,它不像InnoDB那样使用硬件,如果可以的话,InnoDB会将所有工作数据存储在RAM中。最佳解决方案
您需要将这两个表都放在InnoDB中,并避免从磁盘读取。@Mjh谢谢,我正在考虑这一点,但不幸的是,我在表上有全文索引,它在MyISAM中工作得更好。我怀疑为这两个表使用两个不同的存储引擎会对性能产生影响。谢谢,但不幸的是,这一改变毫无帮助。查询持续时间与原始查询大致相同。