文本变量效果查询速度快吗? MySQL的

时间:2015-03-11 11:20:03

标签: mysql performance

我有一个包含2个长文本列的表,当我获取100行需要5秒时,这很长时间了吗? 也许这是因为我有这两个长文本列?

这是表结构:

CREATE TABLE `tempBusiness2` (
  `bussId` int(11) NOT NULL AUTO_INCREMENT,
  `nameHe` varchar(200) COLLATE utf8_bin NOT NULL,
  `nameAr` varchar(200) COLLATE utf8_bin NOT NULL,
  `nameEn` varchar(200) COLLATE utf8_bin NOT NULL,
  `addressHe` varchar(200) COLLATE utf8_bin NOT NULL,
  `addressAr` varchar(200) COLLATE utf8_bin NOT NULL,
  `addressEn` varchar(200) COLLATE utf8_bin NOT NULL,
  `x` varchar(200) COLLATE utf8_bin NOT NULL,
  `y` varchar(200) COLLATE utf8_bin NOT NULL,
  `categoryId` int(11) NOT NULL,
  `subcategoryId` int(11) NOT NULL,
  `cityId` int(11) NOT NULL,
  `cityName` varchar(200) COLLATE utf8_bin NOT NULL,
  `phone` varchar(200) COLLATE utf8_bin NOT NULL,
  `userDetails` text COLLATE utf8_bin NOT NULL,
  `selectedIDFace` tinyint(4) NOT NULL,
  `alluserDetails` longtext COLLATE utf8_bin NOT NULL,
  `details` varchar(500) COLLATE utf8_bin NOT NULL,
  `picture` varchar(200) COLLATE utf8_bin NOT NULL,
  `imageUrl` varchar(200) COLLATE utf8_bin NOT NULL,
  `fax` varchar(200) COLLATE utf8_bin NOT NULL,
  `email` varchar(200) COLLATE utf8_bin NOT NULL,
  `facebook` varchar(200) COLLATE utf8_bin NOT NULL,
  `trash` tinyint(4) NOT NULL,
  `subCategories` varchar(500) COLLATE utf8_bin NOT NULL,
  `openHours` varchar(500) COLLATE utf8_bin NOT NULL,
  `lastCheckedDuplications` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `bussStatus` tinyint(4) NOT NULL,
  `approveStatus` tinyint(4) NOT NULL,
  `steps` tinyint(4) NOT NULL DEFAULT '0',
  `allDetails` longtext COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`bussId`),
  KEY `bussId` (`allDetails`(5),`bussId`),
  KEY `face` (`alluserDetails`(5),`userDetails`(5),`bussId`)
) ENGINE=InnoDB AUTO_INCREMENT=2515926 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

我的查询= SELECT * FROM tempBusiness2 LIMIT 100

2 个答案:

答案 0 :(得分:1)

如果SELECT * FROM tempBusiness2 LIMIT 100确实是您的查询,那么没有 INDEX,而 INDEX会让它运行得更快。

该声明的作用:

  1. 从"数据"的开头开始。 (在InnoDB中,PRIMARY KEY和数据一起聚集在一起。所以,你是巧合地从PK的第一个值开始。)
  2. 阅读那一行。
  3. 转到下一行 - 这很简单有效,因为PK&数据存储在B + Tree结构中。
  4. 重复直至100或表格结束。
  5. 但是......由于TEXT和VARCHAR字段的 lot ,它效率不高。在上面提到的B +树中存储的行不超过8K;剩下的就是坐在与之相连的额外街区。 (我不知道有多少额外的块,但我担心它不止一个。)每个额外的块都是另一个磁盘命中。

    现在,让我们尝试计算磁盘命中数"。如果您第二次运行此查询(并且具有相当大的innodb_buffer_pool_size),则会有任何磁盘命中。相反,让我们专注于"冷缓存"并计算被触摸的数据块。

    如果每个块只有一行(从8KB注释中得出),则需要读取100个块。加上额外的积木 - 一百多个。

    普通磁盘每秒可处理100次读取。这总共是几秒钟 - 可能是你经历的5秒!。

    现在......可以做些什么?

    除非你真的想要所有专栏,否则不要做SELECT *。通过避免一些庞大的列,您可以避免一些磁盘命中。

    innodb_buffer_pool_size应该是可用内存的70%左右。

    "垂直分区" 可以帮助。这是您将某些列拆分为“并行”的地方。表。如果列的某些子集实际上是一大块相关的东西,这是很方便的,如果它是"可选的"在某种意义上。加入"将数据重新组合在一起"可能不会比你现在经历的更糟糕。

    你真的需要(200)在所有这些领域吗?

    你看起来像一个3元素的名字和地址数组。 可能更好,因为另一个表每个bussId最多有3行。

    另一方面说明:如果您对所有查询运行EXPLAIN SELECT ...,您可能会发现"前缀索引"从未使用过:

    KEY `bussId` (`allDetails`(5),`bussId`),
    KEY `face` (`alluserDetails`(5),`userDetails`(5),`bussId`)
    

    你在他们里面想要什么?相反,请考虑使用FULLTEXT索引。

    为什么此表中同时包含city_idcity_name?这听起来像是规范化疯狂了。

答案 1 :(得分:0)

是的,这种列需要花费很多时间,只在您需要时返回此列。 而且,你需要在你的桌子上做一个索引。