精华内容
下载资源
问答
  • 其中包含了与索引相关的一些细节信息其中跟索引有关的using index 在不同的情况下会出现Using index, Using where Using index ,Using index condition等那么Using index Using where;Using index有什么区别?...

    mysql执行计划中的extra列中表明了执行计划的每一步中的实现细节,其中包含了与索引相关的一些细节信息

    其中跟索引有关的using index 在不同的情况下会出现Using index, Using where Using index ,Using index condition等

    那么Using index 和 Using where;Using index 有什么区别?网上搜了一大把文章,说实在话也没怎么弄懂,于是就自己动手试试。

    本文仅从最简单的单表去测试using index 和 using where using index以及简单测试using index condition的情况的出现时机 。

    执行计划的生成与表结构,表数据量,索引结构,统计信息等等上下文等多种环境有关,无法一概而论,复杂情况另论。

    测试环境搭建

    测试表以及测试数据搭建,类似于订单表和订单明细表,暂时先用订单表做测试

    测试表结构

    create table test_order

    (

    id int auto_increment primarykey,user_id int,order_id int,order_status tinyint,create_date datetime

    );

    create table test_orderdetail

    (

    id int auto_increment primarykey,order_id int,product_name varchar(100),cnt int,create_date datetime

    );

    create index idx_userid_order_id_createdate on test_order(user_id,order_id,create_date);

    create index idx_orderid_productname on test_orderdetail(order_id,product_name);

    测试数据(50W)

    CREATE DEFINER=`root`@`%` PROCEDURE `test_insertdata`(IN `loopcount` INT)

    LANGUAGE SQL

    NOT DETERMINISTIC

    CONTAINS SQL

    SQL SECURITY DEFINER

    COMMENT''BEGINdeclare v_uuid varchar(50);while loopcount>0 doset v_uuid=uuid();

    insert into test_order (user_id,order_id,order_status,create_date) values (rand()*1000,id,rand()*10,DATE_ADD(NOW(), INTERVAL - RAND()*20000HOUR));

    insert into test_orderdetail(order_id,product_name,cnt,create_date) values (rand()*100000,v_uuid,rand()*10,DATE_ADD(NOW(), INTERVAL - RAND()*20000HOUR));

    set loopcount= loopcount -1;end while;END

    Using index VS Using where Using index

    首先,在"订单表"上,这里是一个多列复合索引

    create index idx_userid_order_id_createdate on test_order(user_id,order_id,create_date);

    Using index

    1,查询的列被索引覆盖,并且where筛选条件是索引的是前导列,Extra中为Using index

    51cf77167fb2abef46c574be7d2399c0.png

    Using where Using index

    1,查询的列被索引覆盖,并且where筛选条件是索引列之一但是不是索引的不是前导列,Extra中为Using where; Using index,

    意味着无法直接通过索引查找来查询到符合条件的数据

    6b316c7ce0c4c7f2ff5a75260c0b15f2.png

    2,查询的列被索引覆盖,并且where筛选条件是索引列前导列的一个范围,同样意味着无法直接通过索引查找查询到符合条件的数据

    c1847c6f2ed24a9fc21cc50fc9d6fb37.png

    NULL(既没有Using index,也没有Using where Using index,也没有using where)

    1,查询的列未被索引覆盖,并且where筛选条件是索引的前导列,

    意味着用到了索引,但是部分字段未被索引覆盖,必须通过“回表”来实现,不是纯粹地用到了索引,也不是完全没用到索引,Extra中为NULL(没有信息)

    e4058e3050ef8e26fd9ba626ede7dfac.png

    Using where

    1,查询的列未被索引覆盖,where筛选条件非索引的前导列,Extra中为Using where

    6624f73c20b27a167b5b8ac2e52247ac.png

    2,查询的列未被索引覆盖,where筛选条件非索引列,Extra中为Using where

    b7029b06cfa0b456284efab0897a84fd.png

    using where 意味着通过索引或者表扫描的方式进程where条件的过滤,

    反过来说,也就是没有可用的索引查找,当然这里也要考虑索引扫描+回表与表扫描的代价。

    这里的type都是all,说明MySQL认为全表扫描是一种比较低的代价。

    Using index condition

    1,查询的列不全在索引中,where条件中是一个前导列的范围

    0fc51b01b7703bfeab4b13e54e53adf0.png

    2,查询列不完全被索引覆盖,查询条件完全可以使用到索引(进行索引查找)

    dbbc97e0e6235db1efd812078169586d.png

    参考:MySQL · 特性分析 · Index Condition Pushdown (ICP)

    using index conditoin 意味着查询列的某一部分无法直接使用索引

    上述case1中,

    如果禁用ICP(set optimizer_switch='index_condition_pushdown=off'),

    执行计划是using where,意味着全表扫描,如果启用ICP,执行计划为using index Condition,意味着在筛选的过程中实现过滤

    上述case1中

    第二个查询条件无法直接使用索引,隐含了一个查找+筛选的过程。

    两个case的共同点就是无法直接使用索引。

    结论:

    1,Extra中的为Using index的情况

    where筛选列是索引的前导列 &&查询列被索引覆盖 && where筛选条件是一个基于索引前导列的查询,意味着通过索引超找就能直接找到符合条件的数据,并且无须回表

    2,Extra中的为空的情况

    查询列存在未被索引覆盖&&where筛选列是索引的前导列,意味着通过索引超找并且通过“回表”来找到未被索引覆盖的字段,

    3,Extra中的为Using where Using index:

    出现Using where Using index意味着是通过索引扫描(或者表扫描)来实现sql语句执行的,即便是索引前导列的索引范围查找也有一点范围扫描的动作,不管是前非索引前导列引起的,还是非索引列查询引起的。

    尚未解决的问题:

    查询1

    f5a0228730deb3177d2900bdc0d34b5d.png

    查询2

    1e73a5edd35a51207a7856ae704613da.png

    查询3(逻辑上等价于查询1+查询2),执行计划发生了很大的变化。

    21004d1583a7ccc539905219c913b8ba.png

    总结:

    MySQL执行计划中的Extra中信息非常多,不仅仅包括Using index,Using where Using index,Using index condition,Using where,尤其是在多表连接的时候,这一点在相对MSSQL来说,不够直观或者结构化。

    MSSQL中是通过区分索引查找(index seek),索引扫描(index scan),表扫描(table scan)来实现具体的查询的,这图形化的执行计划在不同的场景下是非常直观的,要想完全弄懂MySQL的这个执行计划,可能要更多地在实践中摸索。

    展开全文
  • \ load_image_gt(self.dataset, self.config, image_id, augment=self.augment, augmentation=None, use_mini_mask=self.config.USE_MINI_MASK) else: image, image_meta, gt_class_ids, gt_boxes, gt_masks = \ ...

    使用方法参考这位大佬:https://blog.csdn.net/qq_35874169/article/details/116203228
    这里补充一些细节:
    将 model.py 中的 data_generator() 方法注释掉
    新加上一个 DataGenerator 类,内容如下:

    class DataGenerator(keras.utils.Sequence):
        """A generator that returns images and corresponding target class ids,
        bounding box deltas, and masks.
        dataset: The Dataset object to pick data from
        config: The model config object
        shuffle: If True, shuffles the samples before every epoch
        augment: (deprecated. Use augmentation instead). If true, apply random
            image augmentation. Currently, only horizontal flipping is offered.
        augmentation: Optional. An imgaug (https://github.com/aleju/imgaug) augmentation.
            For example, passing imgaug.augmenters.Fliplr(0.5) flips images
            right/left 50% of the time.
        random_rois: If > 0 then generate proposals to be used to train the
                     network classifier and mask heads. Useful if training
                     the Mask RCNN part without the RPN.
        batch_size: How many images to return in each call
        detection_targets: If True, generate detection targets (class IDs, bbox
            deltas, and masks). Typically for debugging or visualizations because
            in trainig detection targets are generated by DetectionTargetLayer.
        no_augmentation_sources: Optional. List of sources to exclude for
            augmentation. A source is string that identifies a dataset and is
            defined in the Dataset class.
        Returns a Python generator. Upon calling next() on it, the
        generator returns two lists, inputs and outputs. The contents
        of the lists differs depending on the received arguments:
        inputs list:
        - images: [batch, H, W, C]
        - image_meta: [batch, (meta data)] Image details. See compose_image_meta()
        - rpn_match: [batch, N] Integer (1=positive anchor, -1=negative, 0=neutral)
        - rpn_bbox: [batch, N, (dy, dx, log(dh), log(dw))] Anchor bbox deltas.
        - gt_class_ids: [batch, MAX_GT_INSTANCES] Integer class IDs
        - gt_boxes: [batch, MAX_GT_INSTANCES, (y1, x1, y2, x2)]
        - gt_masks: [batch, height, width, MAX_GT_INSTANCES]. The height and width
                    are those of the image unless use_mini_mask is True, in which
                    case they are defined in MINI_MASK_SHAPE.
        outputs list: Usually empty in regular training. But if detection_targets
            is True then the outputs list contains target class_ids, bbox deltas,
            and masks.
        """
    
        def __init__(self, dataset, config, shuffle=True, augment=False, augmentation=None,
                     random_rois=0, batch_size=1, detection_targets=False,
                     no_augmentation_sources=None):
    
            self.image_ids = np.copy(dataset.image_ids)
            self.dataset = dataset
            self.config = config
            self.error_count = 0
    
            # Anchors
            # [anchor_count, (y1, x1, y2, x2)]
            self.backbone_shapes = compute_backbone_shapes(config, config.IMAGE_SHAPE)
            self.anchors = utils.generate_pyramid_anchors(config.RPN_ANCHOR_SCALES,
                                                          config.RPN_ANCHOR_RATIOS,
                                                          self.backbone_shapes,
                                                          config.BACKBONE_STRIDES,
                                                          config.RPN_ANCHOR_STRIDE)
    
            self.shuffle = shuffle
            self.augment = augment
            self.augmentation = augmentation
            self.random_rois = random_rois
            self.batch_size = batch_size
            self.detection_targets = detection_targets
            self.no_augmentation_sources = no_augmentation_sources or []
    
        def __len__(self):
            return int(np.ceil(len(self.image_ids) / float(self.batch_size)))
    
        def __getitem__(self, idx):
            return self.data_generator(self.image_ids[idx * self.batch_size:(idx + 1) * self.batch_size])
    
        def data_generator(self, image_ids):
            b = 0
            while b < self.batch_size:
                try:
                    # Get GT bounding boxes and masks for image.
                    image_id = image_ids[b]
    
                    # If the image source is not to be augmented pass None as augmentation
                    if self.dataset.image_info[image_id]['source'] in self.no_augmentation_sources:
                        image, image_meta, gt_class_ids, gt_boxes, gt_masks = \
                            load_image_gt(self.dataset, self.config, image_id, augment=self.augment,
                                          augmentation=None,
                                          use_mini_mask=self.config.USE_MINI_MASK)
                    else:
                        image, image_meta, gt_class_ids, gt_boxes, gt_masks = \
                            load_image_gt(self.dataset, self.config, image_id, augment=self.augment,
                                          augmentation=self.augmentation,
                                          use_mini_mask=self.config.USE_MINI_MASK)
    
                    # Skip images that have no instances. This can happen in cases
                    # where we train on a subset of classes and the image doesn't
                    # have any of the classes we care about.
                    if not np.any(gt_class_ids > 0):
                        continue
    
                    # RPN Targets
                    rpn_match, rpn_bbox = build_rpn_targets(image.shape, self.anchors,
                                                            gt_class_ids, gt_boxes, self.config)
    
                    # Mask R-CNN Targets
                    if self.random_rois:
                        rpn_rois = generate_random_rois(
                            image.shape, self.random_rois, gt_class_ids, gt_boxes)
                        if self.detection_targets:
                            rois, mrcnn_class_ids, mrcnn_bbox, mrcnn_mask = \
                                build_detection_targets(
                                    rpn_rois, gt_class_ids, gt_boxes, gt_masks, self.config)
    
                    # Init batch arrays
                    if b == 0:
                        batch_image_meta = np.zeros(
                            (self.batch_size,) + image_meta.shape, dtype=image_meta.dtype)
                        batch_rpn_match = np.zeros(
                            [self.batch_size, self.anchors.shape[0], 1], dtype=rpn_match.dtype)
                        batch_rpn_bbox = np.zeros(
                            [self.batch_size, self.config.RPN_TRAIN_ANCHORS_PER_IMAGE, 4], dtype=rpn_bbox.dtype)
                        batch_images = np.zeros(
                            (self.batch_size,) + image.shape, dtype=np.float32)
                        batch_gt_class_ids = np.zeros(
                            (self.batch_size, self.config.MAX_GT_INSTANCES), dtype=np.int32)
                        batch_gt_boxes = np.zeros(
                            (self.batch_size, self.config.MAX_GT_INSTANCES, 4), dtype=np.int32)
                        batch_gt_masks = np.zeros(
                            (self.batch_size, gt_masks.shape[0], gt_masks.shape[1],
                             self.config.MAX_GT_INSTANCES), dtype=gt_masks.dtype)
                        if self.random_rois:
                            batch_rpn_rois = np.zeros(
                                (self.batch_size, rpn_rois.shape[0], 4), dtype=rpn_rois.dtype)
                            if self.detection_targets:
                                batch_rois = np.zeros(
                                    (self.batch_size,) + rois.shape, dtype=rois.dtype)
                                batch_mrcnn_class_ids = np.zeros(
                                    (self.batch_size,) + mrcnn_class_ids.shape, dtype=mrcnn_class_ids.dtype)
                                batch_mrcnn_bbox = np.zeros(
                                    (self.batch_size,) + mrcnn_bbox.shape, dtype=mrcnn_bbox.dtype)
                                batch_mrcnn_mask = np.zeros(
                                    (self.batch_size,) + mrcnn_mask.shape, dtype=mrcnn_mask.dtype)
    
                    # If more instances than fits in the array, sub-sample from them.
                    if gt_boxes.shape[0] > self.config.MAX_GT_INSTANCES:
                        ids = np.random.choice(
                            np.arange(gt_boxes.shape[0]), self.config.MAX_GT_INSTANCES, replace=False)
                        gt_class_ids = gt_class_ids[ids]
                        gt_boxes = gt_boxes[ids]
                        gt_masks = gt_masks[:, :, ids]
    
                    # Add to batch
                    batch_image_meta[b] = image_meta
                    batch_rpn_match[b] = rpn_match[:, np.newaxis]
                    batch_rpn_bbox[b] = rpn_bbox
                    batch_images[b] = mold_image(image.astype(np.float32), self.config)
                    batch_gt_class_ids[b, :gt_class_ids.shape[0]] = gt_class_ids
                    batch_gt_boxes[b, :gt_boxes.shape[0]] = gt_boxes
                    batch_gt_masks[b, :, :, :gt_masks.shape[-1]] = gt_masks
                    if self.random_rois:
                        batch_rpn_rois[b] = rpn_rois
                        if self.detection_targets:
                            batch_rois[b] = rois
                            batch_mrcnn_class_ids[b] = mrcnn_class_ids
                            batch_mrcnn_bbox[b] = mrcnn_bbox
                            batch_mrcnn_mask[b] = mrcnn_mask
                    b += 1
    
                    # Batch full?
                    if b >= self.batch_size:
                        inputs = [batch_images, batch_image_meta, batch_rpn_match, batch_rpn_bbox,
                                  batch_gt_class_ids, batch_gt_boxes, batch_gt_masks]
                        outputs = []
    
                        if self.random_rois:
                            inputs.extend([batch_rpn_rois])
                            if self.detection_targets:
                                inputs.extend([batch_rois])
                                # Keras requires that output and targets have the same number of dimensions
                                batch_mrcnn_class_ids = np.expand_dims(
                                    batch_mrcnn_class_ids, -1)
                                outputs.extend(
                                    [batch_mrcnn_class_ids, batch_mrcnn_bbox, batch_mrcnn_mask])
    
                        return inputs, outputs
    
                except (GeneratorExit, KeyboardInterrupt):
                    raise
                except:
                    # Log it and skip the image
                    logging.exception("Error processing image {}".format(
                        self.dataset.image_info[image_id]))
                    self.error_count += 1
                    if self.error_count > 5:
                        raise
    
        def on_epoch_end(self):
            if self.shuffle:
                np.random.shuffle(self.image_ids)
    

    再将 model.py 中用到 data_generator() 原方法的地方换为 DataGenerator() 即可,如图:
    在这里插入图片描述
    修改完成运行就不会有这个提示,亲测 : D

    展开全文
  • Use augmentation instead). If true, apply random image augmentation. Currently, only horizontal flipping is offered. augmentation: Optional. An imgaug (https://github.com/aleju/imgaug) augmentation. ...

        删除 data_generator(),其他不需要修改,换成下面的,然后在调用的地方记得也改一下,亲测可用:

    class DataGenerator(keras.utils.Sequence):
        """A generator that returns images and corresponding target class ids,
        bounding box deltas, and masks.
        dataset: The Dataset object to pick data from
        config: The model config object
        shuffle: If True, shuffles the samples before every epoch
        augment: (deprecated. Use augmentation instead). If true, apply random
            image augmentation. Currently, only horizontal flipping is offered.
        augmentation: Optional. An imgaug (https://github.com/aleju/imgaug) augmentation.
            For example, passing imgaug.augmenters.Fliplr(0.5) flips images
            right/left 50% of the time.
        random_rois: If > 0 then generate proposals to be used to train the
                     network classifier and mask heads. Useful if training
                     the Mask RCNN part without the RPN.
        batch_size: How many images to return in each call
        detection_targets: If True, generate detection targets (class IDs, bbox
            deltas, and masks). Typically for debugging or visualizations because
            in trainig detection targets are generated by DetectionTargetLayer.
        no_augmentation_sources: Optional. List of sources to exclude for
            augmentation. A source is string that identifies a dataset and is
            defined in the Dataset class.
        Returns a Python generator. Upon calling next() on it, the
        generator returns two lists, inputs and outputs. The contents
        of the lists differs depending on the received arguments:
        inputs list:
        - images: [batch, H, W, C]
        - image_meta: [batch, (meta data)] Image details. See compose_image_meta()
        - rpn_match: [batch, N] Integer (1=positive anchor, -1=negative, 0=neutral)
        - rpn_bbox: [batch, N, (dy, dx, log(dh), log(dw))] Anchor bbox deltas.
        - gt_class_ids: [batch, MAX_GT_INSTANCES] Integer class IDs
        - gt_boxes: [batch, MAX_GT_INSTANCES, (y1, x1, y2, x2)]
        - gt_masks: [batch, height, width, MAX_GT_INSTANCES]. The height and width
                    are those of the image unless use_mini_mask is True, in which
                    case they are defined in MINI_MASK_SHAPE.
        outputs list: Usually empty in regular training. But if detection_targets
            is True then the outputs list contains target class_ids, bbox deltas,
            and masks.
        """
    
        def __init__(self, dataset, config, shuffle=True, augment=False, augmentation=None,
                     random_rois=0, batch_size=1, detection_targets=False,
                     no_augmentation_sources=None):
    
            self.image_ids = np.copy(dataset.image_ids)
            self.dataset = dataset
            self.config = config
            self.error_count = 0
    
            # Anchors
            # [anchor_count, (y1, x1, y2, x2)]
            self.backbone_shapes = compute_backbone_shapes(config, config.IMAGE_SHAPE)
            self.anchors = utils.generate_pyramid_anchors(config.RPN_ANCHOR_SCALES,
                                                          config.RPN_ANCHOR_RATIOS,
                                                          self.backbone_shapes,
                                                          config.BACKBONE_STRIDES,
                                                          config.RPN_ANCHOR_STRIDE)
    
            self.shuffle = shuffle
            self.augment = augment
            self.augmentation = augmentation
            self.random_rois = random_rois
            self.batch_size = batch_size
            self.detection_targets = detection_targets
            self.no_augmentation_sources = no_augmentation_sources or []
    
        def __len__(self):
            return int(np.ceil(len(self.image_ids) / float(self.batch_size)))
    
        def __getitem__(self, idx):
            return self.data_generator(self.image_ids[idx * self.batch_size:(idx + 1) * self.batch_size])
    
        def data_generator(self, image_ids):
            b = 0
            while b < self.batch_size:
                try:
                    # Get GT bounding boxes and masks for image.
                    image_id = image_ids[b]
    
                    # If the image source is not to be augmented pass None as augmentation
                    if self.dataset.image_info[image_id]['source'] in self.no_augmentation_sources:
                        image, image_meta, gt_class_ids, gt_boxes, gt_masks = \
                            load_image_gt(self.dataset, self.config, image_id, augment=self.augment,
                                          augmentation=None,
                                          use_mini_mask=self.config.USE_MINI_MASK)
                    else:
                        image, image_meta, gt_class_ids, gt_boxes, gt_masks = \
                            load_image_gt(self.dataset, self.config, image_id, augment=self.augment,
                                          augmentation=self.augmentation,
                                          use_mini_mask=self.config.USE_MINI_MASK)
    
                    # Skip images that have no instances. This can happen in cases
                    # where we train on a subset of classes and the image doesn't
                    # have any of the classes we care about.
                    if not np.any(gt_class_ids > 0):
                        continue
    
                    # RPN Targets
                    rpn_match, rpn_bbox = build_rpn_targets(image.shape, self.anchors,
                                                            gt_class_ids, gt_boxes, self.config)
    
                    # Mask R-CNN Targets
                    if self.random_rois:
                        rpn_rois = generate_random_rois(
                            image.shape, self.random_rois, gt_class_ids, gt_boxes)
                        if self.detection_targets:
                            rois, mrcnn_class_ids, mrcnn_bbox, mrcnn_mask = \
                                build_detection_targets(
                                    rpn_rois, gt_class_ids, gt_boxes, gt_masks, self.config)
    
                    # Init batch arrays
                    if b == 0:
                        batch_image_meta = np.zeros(
                            (self.batch_size,) + image_meta.shape, dtype=image_meta.dtype)
                        batch_rpn_match = np.zeros(
                            [self.batch_size, self.anchors.shape[0], 1], dtype=rpn_match.dtype)
                        batch_rpn_bbox = np.zeros(
                            [self.batch_size, self.config.RPN_TRAIN_ANCHORS_PER_IMAGE, 4], dtype=rpn_bbox.dtype)
                        batch_images = np.zeros(
                            (self.batch_size,) + image.shape, dtype=np.float32)
                        batch_gt_class_ids = np.zeros(
                            (self.batch_size, self.config.MAX_GT_INSTANCES), dtype=np.int32)
                        batch_gt_boxes = np.zeros(
                            (self.batch_size, self.config.MAX_GT_INSTANCES, 4), dtype=np.int32)
                        batch_gt_masks = np.zeros(
                            (self.batch_size, gt_masks.shape[0], gt_masks.shape[1],
                             self.config.MAX_GT_INSTANCES), dtype=gt_masks.dtype)
                        if self.random_rois:
                            batch_rpn_rois = np.zeros(
                                (self.batch_size, rpn_rois.shape[0], 4), dtype=rpn_rois.dtype)
                            if self.detection_targets:
                                batch_rois = np.zeros(
                                    (self.batch_size,) + rois.shape, dtype=rois.dtype)
                                batch_mrcnn_class_ids = np.zeros(
                                    (self.batch_size,) + mrcnn_class_ids.shape, dtype=mrcnn_class_ids.dtype)
                                batch_mrcnn_bbox = np.zeros(
                                    (self.batch_size,) + mrcnn_bbox.shape, dtype=mrcnn_bbox.dtype)
                                batch_mrcnn_mask = np.zeros(
                                    (self.batch_size,) + mrcnn_mask.shape, dtype=mrcnn_mask.dtype)
    
                    # If more instances than fits in the array, sub-sample from them.
                    if gt_boxes.shape[0] > self.config.MAX_GT_INSTANCES:
                        ids = np.random.choice(
                            np.arange(gt_boxes.shape[0]), self.config.MAX_GT_INSTANCES, replace=False)
                        gt_class_ids = gt_class_ids[ids]
                        gt_boxes = gt_boxes[ids]
                        gt_masks = gt_masks[:, :, ids]
    
                    # Add to batch
                    batch_image_meta[b] = image_meta
                    batch_rpn_match[b] = rpn_match[:, np.newaxis]
                    batch_rpn_bbox[b] = rpn_bbox
                    batch_images[b] = mold_image(image.astype(np.float32), self.config)
                    batch_gt_class_ids[b, :gt_class_ids.shape[0]] = gt_class_ids
                    batch_gt_boxes[b, :gt_boxes.shape[0]] = gt_boxes
                    batch_gt_masks[b, :, :, :gt_masks.shape[-1]] = gt_masks
                    if self.random_rois:
                        batch_rpn_rois[b] = rpn_rois
                        if self.detection_targets:
                            batch_rois[b] = rois
                            batch_mrcnn_class_ids[b] = mrcnn_class_ids
                            batch_mrcnn_bbox[b] = mrcnn_bbox
                            batch_mrcnn_mask[b] = mrcnn_mask
                    b += 1
    
                    # Batch full?
                    if b >= self.batch_size:
                        inputs = [batch_images, batch_image_meta, batch_rpn_match, batch_rpn_bbox,
                                  batch_gt_class_ids, batch_gt_boxes, batch_gt_masks]
                        outputs = []
    
                        if self.random_rois:
                            inputs.extend([batch_rpn_rois])
                            if self.detection_targets:
                                inputs.extend([batch_rois])
                                # Keras requires that output and targets have the same number of dimensions
                                batch_mrcnn_class_ids = np.expand_dims(
                                    batch_mrcnn_class_ids, -1)
                                outputs.extend(
                                    [batch_mrcnn_class_ids, batch_mrcnn_bbox, batch_mrcnn_mask])
    
                        return inputs, outputs
    
                except (GeneratorExit, KeyboardInterrupt):
                    raise
                except:
                    # Log it and skip the image
                    logging.exception("Error processing image {}".format(
                        self.dataset.image_info[image_id]))
                    self.error_count += 1
                    if self.error_count > 5:
                        raise
    
        def on_epoch_end(self):
            if self.shuffle:
                np.random.shuffle(self.image_ids)
    

    来源:此链接

    展开全文
  • 本系列文章目录 展开/收起 Mysql索引篇(一) 索引的数据... Mysql索引篇(四) 覆盖索引(Using index)、文件排序(Using filesort)临时表(Using temporary) ...
     
    

    Using index 覆盖索引

    概念:一个索引(B+树)中包含所有需要查询的字段的值,称为覆盖索引。覆盖索引的一个特点是无需回表。
    覆盖索引不是一种索引类型,不是一个名词,而是一个动词。

    下面举一个渐进的例子来描述覆盖索引在底层上是怎么做的:
    比如,我给 col1 字段设置了一个普通索引,给id设置了主键索引,使用的是innodb的表。

    1.Select * from t;
    全表扫描,在底层表现为在聚集索引这棵树中把所有叶子节点一个个的读取到内存中,获取每个叶节点内的行数据。

    2.Select col1 from t;
    Mysql检查到 col1 字段是索引,所以会直接去索引获取col1字段,因为col1索引B+树中就包含col1字段的值,无需拿到叶子节点中存储的主键id值再跳到聚集索引获取col1的数据。此时直接找到二级索引的B+树将所有叶子节点的col1的值获取到。这个过程只查了col1二级索引的B+树,没有去查主键索引的B+树,因此这个例子就用到了覆盖索引。

    3.假设我现在把col1的索引删了,再去执行 select col1from t;请问会发生什么变化?

    我们还是要在脑袋里构建B+树的图:
    有col1索引的时候,会直接去col1的B+树中去找,并且把所有叶子节点读取到内存中(假设有n个叶子节点,3层,就进行了3-1 + n-1=n+1次io操作),并在内存中找出每个叶子节点的col1值。

    没有col1索引的时候,会去主键索引的B+树中去找,并且也把所有的叶子节点读取到内存,也是发生了 n+1 次io操作。

    好像没什么区别,都是n+1次io操作,但真的没区别吗?

    主键索引的叶子节点存了所有表字段的数据,每一个节点从磁盘读取到内存的时候都会把一行中所有表字段的数据读到内存。然后在内存中,mysql程序再从多个行的多个表字段中获取其中的col1字段。
    col1索引的叶子节点只存了col1和id这两个字段的数据。每一个节点从磁盘读取到内存的时候只把col1和id的值加载到内存。然后只要col1,不要id。

    也就是说虽然两者之间的io操作次数相同,但是前者每次io操作的速度比后者快,因为二级索引每个节点的数据比主键索引的每个节点的数据少,io读写的数据量不同会影响io的速度的。

    为了读取col1字段而把其他全部字段都读取到内存,这就没有用到覆盖索引,还是一个全表扫描。

    我有试过在一个100万的文章表中执行 select title from article 查询所有title。
    加title索引的时候耗时0.03秒,不加title索引的时候耗时56秒。

    所以不要小看 覆盖索引 的作用,它在特定情境下可以带来极大的优化。

    4.Select id from t;
    分别在innodb引擎和myisam引擎下执行这个语句,请问有没有用到覆盖索引?
    答案是有,因为id建立了主键索引,所以直接会去主键索引的树中读取所有叶节点的key但是不会去读取value(主键索引中叶节点的key就是id)。两种引擎下都没有回表。

    5.Select id from t where col1>100;
    假设我给col1加了普通索引,分别在innodb引擎和myisam引擎下执行这个语句,请问有没有用到覆盖索引?

    答案是,innodb和myisam都用到了二级索引查col1(type是range),但是innodb引擎用到了覆盖索引,myisam没用到覆盖索引。

    首先,加了条件 col1>100后,就会去col1这个二级索引的树中查(而不会直接在主键索引中查)满足 col1>100的叶子节点,innodb和myisam都需要做这一步。

    但是innodb的二级索引的叶子节点存储着col1的值和对应的id值。因此只需访问二级索引这一棵B+树就能获取到全部id,无需回表到主键索引去拿id字段。
    而myisam的二级索引的叶子节点中,叶子节点只有col1,没有id,所以需要通过叶子节点存储的行地址到MYD文件中找对应的行,再从这些行中提取id字段。

    也就是说,innodb在这个过程中没有回表,而myisam发生了回表。


    我有试过在一个100万的文章表中执行 select id from article where create_time > 1586421023 。
    Create_time加了索引,在innodb的表中查只花了0.7秒,在myisam的表中查花了31.67秒


    6.Select id from t where col2>100
    现在我添加了联合索引 index col1_col2 (col1,col2)。
    请问在innodb引擎下,是否用到了覆盖索引?

    答案是用到了联合索引的覆盖索引,只是条件查找没有用到联合索引而已(意思是 Extra中有Using index,但是type中没有出现range而是All)。
    底层发生了什么?首先 mysql 会思考说主人想搜索id,id在主键索引和二级索引这两棵树中都有,可是如果在主键索引中搜,为了判断col2>100这个条件,mysql会把所有叶子节点从磁盘读到内存,主键索引的叶子节点是包含很多字段的,这会很慢。如果在联合索引中搜索,由于col2>100不符合联合索引的最左前缀原则,所以mysql也会把全部叶子节点从磁盘读到内存,在内存中筛选 col2>100的节点,并获取id字段的值。
    所以这就是为什么用到了覆盖索引,但是范围查询没用到联合索引的原因。

    7.Select col1,col2,col3 from t where col1 > 100;
    现在我添加了联合索引 index col1_col2 (col1,col2)。
    请问在innodb引擎下,是否用到了覆盖索引?

    答案是范围查询用到了二级索引(因为where col1>100遵循了最左前缀原则),但是查字段的时候由于col3不在二级索引的叶子节点中,所以需要回表到主键索引的叶子节点中找col3字段。所以没有用到覆盖索引。
    不过因为在二级索引中用到了range,所以mysql不会加载所有主键索引的叶子节点,而是加载对应id的叶子节点。


    8.Select col1,col2,col3 from t where col2 > 100;
    这句完全没用到联合索引,单纯的一个全表扫表,直接在主键索引读取所有的叶节点。Col2的条件判断和col1,col2,col3的字段提取全在内存中计算完成。


    总结:无论判断一条sql有没有用到索引,有没有用到覆盖索引,都可以通过画一个B+树的图来分析。知道底层原理,sql优化变得有理有据,不知道底层原理,sql优化就只能凭感觉。

     

     

    Using FileSort 文件排序

    在Sql优化中,我们希望尽可能不要出现文件排序,因为出现了文件排序意味着没有使用到索引构建好的排序,而是需要在内存中对字段进行重新排序,排序的过程是计算的过程比较消耗cpu。

    多字段排序要尽量遵循最左前缀原则,而且不要对一个字段升序对另一个字段降序,否则也会使用到Using filesort

    如果一定会发生 Using filesort,那么我们要了解的文件排序有两种方式:双路排序和单路排序

    举个例子:

    一个表建立的联合索引 index age_salary (age, salary)

    Select * from t where id>500 and id<1000 order by  salary, age;

    上面的例子中:

    双路排序会在二级索引的B+树取出满足where条件的行(501~999行)的salary和age字段(不会取其他字段),和501~999行的地址指针,然后在sort buffer内存中排序。如果sort buffer不够(要排序的salary和age太多了),此时会创建一个 temporary table 存储结果(临时表的出现意味着更多次的io)。排完序之后再根据行指针(这是的行指针也是排好序的)回表(回到主键索引)取记录(排序的时候只取了要排序的字段,现在回表是要取整行的所有字段)。

     

    单路排序会取出满足where条件的行(501~999行)的所有字段(不过这样更容易生成临时表,这样的话io反而会比双路排序高),然后再sort buffer中根据salary 和 age字段排序,然后直接输出结果。

     

    由于双路排序发生了回表,所以大大增加了io次数(是单路排序的两倍,如果单路排序不生成临时表的话), 但是单路排序的内存开销更大,更容易在排序过程中生成临时表,从而增加io次数。

    Mysql会根据情况选择其中当然一种算法来进行文件排序filesort。但无论是哪种排序我们都可以通过提高 sort_buffer_size 和 max_length_for_sort_data来增大排序缓冲区的大小,减小创建临时表的可能。

     

    结论:在非要出现文件排序不可的情况下,可以通过增大排序缓冲区的大小来优化

     

    Using Temporary  使用临时表

    临时表可以有我们用户手动创建,也可能是在执行sql是mysql在内部创建。我们只讨论后者。
    MySQL临时表分为“内存临时表”和“磁盘临时表”,其中内存临时表使用MySQL的MEMORY存储引擎,磁盘临时表使用MySQL的MyISAM存储引擎;一般情况下,MySQL会先创建内存临时表,但内存临时表超过配置指定的值后,MySQL会将内存临时表导出到磁盘临时表;

    mysql会在什么时候创建内部临时表?(一般都是内存不够用的时候)
    A.在排序或者分组过程中由于内存不足而导致mysql创建临时表进行额外存储。
    B.在JOIN查询中,ORDER BY或者GROUP BY使用了不是第一个表的列
    C.排序或分组时,表包含TEXT或者BLOB列(这样对于单路排序而言sort buffer肯定不足);
    D.GROUP BY 或者 DISTINCT 子句中包含长度大于512字节的列;
    E.使用UNION或者UNION ALL时,SELECT子句中包含大于512字节的列;
    最后3个是直接使用磁盘临时表。

    为了避免使用到临时表,我们可以在排序和分组的时候尽量是去对索引的字段来排序分组,而且不能让索引失效。再者拆分长度很长的列,例如将Text或者Blob类型的字段垂直分表到另一张表中。

    临时表的危害是大大增加io次数,严重时导致磁盘读写压力过大。

    本文转载自: 张柏沛IT技术博客 > Mysql索引篇(四) 覆盖索引(Using index)、文件排序(Using filesort)和临时表(Using temporary)
    展开全文
  • composer 安装 omposer require lcobucci/jwt:3.3.3
  • 解决 C# 中 Using 'UseMvcWithDefaultRoute' to configure MVC is not supported while using Endpoint Routin1. 原因2. 解决 1. 原因 版本更新导致 2. 解决 将 app.UseMvcWithDefaultRoute(); app.Run(async ...
  • 出现这类原因时 是编译器认为 你的 scanf函数不安全 ,才报的错或警告,这里我们要明白的是 scanf 是c语言提供的 ,而scanf_s 不是标准c语言提供的,而是vs编译器提供的 这里不建议使用 scanf_s 因为 你用它的话,...
  • Using --password via the CLI is insecure. Use --password-stdin.提示 解决: 1. 将密码写入到一个文件中,例如/etc/docker_passwd文件 2.使用以下命令执行登录: cat /etc/docker_passwd | docker login ...
  • 项目刚刚告一段落,boos又让优化几个主要界面程序代码方便的优化就不讲了,主要说MySQL的优化首先查看explain执行计划,让主要查询语句使用索引,索引type级别最好达到ref | ref_eq级别其次将extra一栏的Using ...
  • 今天更新了VisualVM 2.0.5,启动的时候提示找不到jdk引用,于是到包内部的visualvm.conf中修改jdk引用地址。 visualvm.conf的路径 /Applications/VisualVM.app/Contents/Resources/visualvm/etc/visualvm.conf ...
  • yld: warning: could not load inserted library 'dumpdecrypted.dylib' into ... dumpdecrypted.dylib: code signature in (dumpdecrypted.dylib) not valid for use in process using Library Validation: mappe
  • Spark SQL错误提示(You need … setting useSSL=false, or set useSSL=true… Exception in thread “main” java.sql.SQLException: Access denied for user ‘root’@‘localhost’ (using password: YES) ) ...
  • react引入antd后报出黄色警告You are using a whole package of antd, please use https://www.npmjs.com/package/babel-plugin-import 此时需要引入babel-plugin-import按需加载 npm install babel-plugin-...
  • 问题: 如下:
  • 在使用v-for的时候,控制台报错,Avoid using non-primitive value as key, use string/number value instead. 主要是原因是key用的不对, key是要唯一性的,所以应该用循环的数据里面唯一的来做,比如id,如下,我的...
  • You are using a whole package of antd-mobile, please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size. 1、此时需要引入babel-plugin-import按需加载 npm install babel-...
  • 报错:[Err] 1064 – You have an error in your... check the manual that corresponds to your MySQL server version for the right syntax to use near ‘USING BTREE,KEY `Email` (`Email`) USING BTREE分析问题...
  • VUE渲染时报错 Avoid using non-primitive value as key, use string/number value instead. 进入页面,就会冒出这么一长串的报错,这个是由于v-for循环里,key值可能重复了,所以会报这个错。查看了一下页面代码:...
  • 在配置OpenGL的时候出现以下...To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 解决办法-》在项目上右键-》进入属性 配置属性->C/C+±>预处理器->预处理器定义-&g
  • 使用修饰器报错 用create-react-app脚手架搭建react项目 在使用到mobx的时候 用到了修饰器 报了以上错误 百度了一下,发现是使用修饰器之后,eslint会报错 解决方案如下: 打开package.json 找到 eslintConfig ...
  • vue渲染列表时报错Avoid using non-primitive value as key, use string/number value instead. 错误: 这个是由于v-for循环里,key值可能重复了,所以会报这个错。查看了一下页面代码: 发现key值重复了 key...
  • 那么问题来了这个报错是什么意思呢??? 还是老方法,先暴力翻译一下报错语句的意思: key值是必须唯一的,如果重复就会报错 可以把key值改为index或者id,就可以避免这个情况(这里key最好用id,才能达到key值...
  • But instead of using the iPod software on the iPhone, I now use the very promissing pwnplayer which is able to play music from the iPod library on you iPhone, as well as MP’3 you copied to a ...
  • (Emitted value instead of an instance of Error) Do not use v-for index as key on <transition-group> children, this is the same as not using keys. 如:将v-for="(item,index) in list"的:key="index...
  • 如果MySQL在创建表时, 出现the right syntax to use near USING BTREE这样的错误,莫惊慌,因为这是MySQL的版本引起的。使用下面的SQL语句创建表:CREATE TABLE `message_info_tbl` (`id` int(10) unsigned NOT ...
  • Using where:过滤元素;执行explain SELECT * from test where b = '4' (b不是索引,全表扫描后,通过过滤获取所需数据) 执行explain SELECT * from test where c = '4' (c是索引,通过索引定位到所需数据,不需...
  • 在MySQL JOIN中,ON和USING()有什么区别? 据我所知,USING()只是语法更方便,而ON在列名不同时允许更多的灵活性。 但是,这种差别是如此之小,您可能会认为他们只是取消了USING()。除了眼球以外,还有什么呢? 如果...
  • It is used as the outermost element of SVG documents, but it can also be used to embed an SVG fragment inside an SVG or HTML document.svg 元素是一个容器,它定义了一个新的坐标系视口。...
  • COALESCE()函数 1. 函数解释 命令格式:coalesce(expr 1,expr 2,…);...返回值:返回值类型参数类型相同 2. 示例 题目:Use COALESCE to print the mobile number. Use the number ‘07986 444 2266’ if
  • oracle使用using关键字

    2021-01-12 21:08:44
    今天在看书,看到SQL中用到了using字句,学习了一下,简单说下 using字句可以实现内连接:select * from emp join dept using(deptno); 等同于:select * from emp e,dept d where e.deptno = d.deptno; 详细讲解...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 862,850
精华内容 345,140
关键字:

using和use的区别