Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.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
Mysql 我可以做些什么来提高SQL的效率?(表中有850K行)_Mysql_Sql_Performance - Fatal编程技术网

Mysql 我可以做些什么来提高SQL的效率?(表中有850K行)

Mysql 我可以做些什么来提高SQL的效率?(表中有850K行),mysql,sql,performance,Mysql,Sql,Performance,由于生产问题,我一直在mysql上运行缓慢的日志,第一个查询是: select * from feeditem feeditem0_ where feeditem0_.importance=0 and feeditem0_.company_id=N limit 21; 我将select(N是FK的id)缩写为它是从hibernate生成的,它只是选择表中的所有字段。当我进行mysql解释时,我得到: explain select * from feeditem feeditem0_ where

由于生产问题,我一直在mysql上运行缓慢的日志,第一个查询是:

select * from feeditem feeditem0_ where feeditem0_.importance=0 and feeditem0_.company_id=N limit 21;
我将select(N是FK的id)缩写为它是从hibernate生成的,它只是选择表中的所有字段。当我进行mysql解释时,我得到:

explain select * from feeditem feeditem0_ where feeditem0_.importance=0 and    feeditem0_.company_id=5045 limit 21 \G;;
*************************** 1. row ***************************
       id: 1
select_type: SIMPLE
    table: feeditem0_
     type: index_merge
possible_keys: FKF49961B13D5FD8EF,importance
      key: FKF49961B13D5FD8EF,importance
  key_len: 9,5
      ref: NULL
     rows: 2422
    Extra: Using intersect(FKF49961B13D5FD8EF,importance); Using where
该表中大约有85000行

模式是:

CREATE TABLE `feeditem` (
`DTYPE` varchar(31) NOT NULL,
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`dateCreated` datetime DEFAULT NULL,
`endSentance` varchar(255) DEFAULT NULL,
`importance` int(11) DEFAULT NULL,
`startSentance` varchar(255) DEFAULT NULL,
`summary` varchar(255) DEFAULT NULL,
`summaryComplete` bit(1) NOT NULL,
`targetId` bigint(20) DEFAULT NULL,
`targetSentance` text,
`type` varchar(255) NOT NULL,
`hasRead` bit(1) DEFAULT NULL,
`teamProject_id` bigint(20) DEFAULT NULL,
`user_id` bigint(20) DEFAULT NULL,
`usertoread_id` bigint(20) DEFAULT NULL,
`contentType` varchar(255) DEFAULT NULL,
`company_id` bigint(20) DEFAULT NULL,
`updated` int(1) unsigned DEFAULT NULL,
`feedType` varchar(255) DEFAULT NULL,
`extraInfo` varchar(255) DEFAULT NULL,
`extraTargetId` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FKF49961B1B74A2DA5` (`user_id`),  
KEY `FKF49961B17CE9E5EF` (`teamProject_id`),
KEY `FKF49961B137B7D1B4` (`usertoread_id`),
KEY `FKF49961B13D5FD8EF` (`company_id`),
KEY `importance` (`importance`),
KEY `dateCreated` (`dateCreated`)
) ENGINE=InnoDB AUTO_INCREMENT=956498 DEFAULT CHARSET=utf8
有没有办法阻止我扫描2400多行?这是慢速日志的摘要(使用mysqlsla):

谢谢

更新1:我添加了另一个2列索引(称为feedquery),但优化器似乎选择不使用该索引:

mysql> explain select id from feeditem feeditem0_ where feeditem0_.importance=0 and    feeditem0_.company_id=5045  \G;
*************************** 1. row ***************************
       id: 1
  select_type: SIMPLE
    table: feeditem0_
     type: index_merge
possible_keys: FKF49961B13D5FD8EF,importance,feedquery
      key: FKF49961B13D5FD8EF,feedquery
  key_len: 9,14
      ref: NULL
     rows: 2753
    Extra: Using intersect(FKF49961B13D5FD8EF,feedquery); Using where; Using index
 explain select id from feeditem feeditem0_ ignore index (FKF49961B13D5FD8EF) where feeditem0_.importance=0 and  feeditem0_.company_id=5045  \G;
 *************************** 1. row ***************************
       id: 1
 select_type: SIMPLE
    table: feeditem0_
     type: ref
 possible_keys: importance,feedquery
      key: feedquery
  key_len: 14
      ref: const,const
     rows: 8496
    Extra: Using where; Using index
如果忽略索引:

mysql> explain select id from feeditem feeditem0_ where feeditem0_.importance=0 and    feeditem0_.company_id=5045  \G;
*************************** 1. row ***************************
       id: 1
  select_type: SIMPLE
    table: feeditem0_
     type: index_merge
possible_keys: FKF49961B13D5FD8EF,importance,feedquery
      key: FKF49961B13D5FD8EF,feedquery
  key_len: 9,14
      ref: NULL
     rows: 2753
    Extra: Using intersect(FKF49961B13D5FD8EF,feedquery); Using where; Using index
 explain select id from feeditem feeditem0_ ignore index (FKF49961B13D5FD8EF) where feeditem0_.importance=0 and  feeditem0_.company_id=5045  \G;
 *************************** 1. row ***************************
       id: 1
 select_type: SIMPLE
    table: feeditem0_
     type: ref
 possible_keys: importance,feedquery
      key: feedquery
  key_len: 14
      ref: const,const
     rows: 8496
    Extra: Using where; Using index
下表:

CREATE TABLE `feeditem` (
.....
PRIMARY KEY  (`id`),
KEY `FKF49961B1B74A2DA5` (`user_id`),
 KEY `FKF49961B17CE9E5EF` (`teamProject_id`),
KEY `FKF49961B137B7D1B4` (`usertoread_id`),
KEY `FKF49961B13D5FD8EF` (`company_id`),
KEY `importance` (`importance`),
KEY `dateCreated` (`dateCreated`),
KEY `feedquery` (`importance`,`company_id`)
) ENGINE=InnoDB AUTO_INCREMENT=999359 DEFAULT CHARSET=utf8 
更新2:@Salman A

SHOW profile;
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000342 |
| checking permissions | 0.000024 |
| Opening tables       | 0.000053 |
| System lock          | 0.000027 |
| init                 | 0.000166 |
| optimizing           | 0.000068 |
| statistics           | 0.012869 |
| preparing            | 0.000202 |
| executing            | 0.000008 |
| Sending data         | 0.332767 |
| end                  | 0.000022 |
| query end            | 0.000009 |
| closing tables       | 0.000016 |
| freeing items        | 0.000040 |
| logging slow query   | 0.000005 |
| cleaning up          | 0.000014 |
+----------------------+----------+

ibdata1大约为1.5gb

一个标准的
从y中选择x,其中z
(这是您所拥有的,只是有多个条件)是您可以运行的最有效的查询之一。你唯一能真正添加的是一个包含所有你正在查询的列的索引;但是,写入此表时,这将影响性能。(以及首次填充该指数的高一次命中率)

如果您知道查询中的一列比其他列对结果的限制要大得多,那么可以折衷一下,只在该查询上添加一个索引。例如,如果只查找company_id=x的行可以保证只剩下几行要过滤掉,那么最好只在该列上设置索引。

一般答案:

  • 除非绝对需要所有列,否则不要使用
    SELECT*
    。选择只需要的列
  • 添加一个
    orderby
    子句或
    LIMIT
    没有太大意义
  • 创建一个包含以下内容的复合(即多列)索引
    • 重要性
      公司id
    • 要按预期顺序排序的字段
    • 希望
      选择
      返回的任何其他字段(代替
      *
  • 通过这种方式,DB引擎可以通过单个索引查找操作、覆盖排序以及直接从索引中查找其他列来查找与搜索的直接匹配。索引包含其涵盖的所有列的副本;如果所有请求的数据都驻留在索引中,则无需遍历实际的表。这将提高查询效率

    请注意,这是空间交换的速度。添加到索引中的每一列都会增加其物理大小,因此请明智地选择

    编辑1:此外,索引对写入操作的速度有影响-插入、更新和删除查询将由于索引维护而稍微慢一点-交换条件是选择速度更快。(谢谢你的评论,@Thor84no)

    编辑2:如果此查询是表的主要使用模式,并且表没有太大变化(这一点非常重要!),则可以考虑创建聚集索引。聚集索引表示基表的物理排序,与其他索引一样,它不存在于基表之外。每次更改聚集索引的定义或添加/删除“中间”现有记录中的行时,实际数据都会在物理上重新排序,即在磁盘上重新排序,这是您希望避免的昂贵操作


    有时这可能是一件明智的事情,但在你的情况下,很可能不是。如果您的表是某种类型的日志表,请将聚集索引保持在自动递增ID。

    基本上,由于每个索引只包含WHERE子句中引用的两个字段中的一个,引擎需要获取满足第一部分的记录和满足第二部分的记录(通过使用索引)分别为“重要性”和“FKF49961B13D5FD8EF”)


    生成索引的简单规则是,您希望索引与WHERE子句中的字段完全相同。因此,您可以使用“重要性”和“公司id”创建索引“按这个顺序。这将精确地选择匹配的行,2.4k行将不再被扫描。

    通常写性能的降低比索引占用的额外磁盘空间更大,所以我也要提到这一点。这就是我(现在)得到的答案,但优化器似乎忽略了它。我的建议是现在使用MySQL的索引提示选项尝试运行时。