关于MOVE的一系列redo size的实验

博客提及需了解move机制,并给出相关链接http://blog.youkuaiyun.com/dlinger/archive/2004/07/12/39667.aspx ,涉及数据库相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们首先需要了解一下move的机制:

http://blog.youkuaiyun.com/dlinger/archive/2004/07/12/39667.aspx

现在看看tablespace的信息:

SQL> select tablespace_name,SEGMENT_SPACE_MANAGEMENT from dba_tablespaces where tablespace_name in('ASSM','HWM');

 

TABLESPACE_NAME                SEGMENT_SPACE_MANAGEMENT

 

------------------------------ ------------------------

 

ASSM                                          AUTO

 

HWM                                           MANUAL

 

Oracle版本信息:

SQL> select * from v$version;

 

BANNER

----------------------------------------------------------------

Oracle Database 10g Enterprise Edition Release 10.1.0 .2.0 - Prod

PL/SQL Release 10.1.0 .2.0 - Production

CORE    10.1.0 .2.0      Production

TNS for 32-bit Windows: Version 10.1.0 .2.0 - Production

NLSRTL Version 10.1.0 .2.0 – Production

 

 

1.归档模式下: segment ASSM

 

SQL> create table my_objects  tablespace ASSM as

select * from all_objects where rownum<20000;

 

Table created

 

SQL> delete from my_objects where object_name like '%C%';

 

7278 rows deleted

 

SQL> commit;

 

Commit complete

 

SQL> delete from my_objects where object_name like '%U%';

 

2732 rows deleted

 

SQL> commit;

 

Commit complete

 

SQL> select value from v$mystat, v$statname

where v$mystat.statistic# = v$statname.statistic# 

and  v$statname.name = 'redo size';

 

     VALUE

----------

   5991164

 

SQL> alter table my_objects move;

 

Table altered

 

SQL> select value from v$mystat, v$statname

where v$mystat.statistic# = v$statname.statistic#

and  v$statname.name = 'redo size';

 

     VALUE

----------

   7220956

 

SQL> select 7220956-5991164 from dual;

 

7220956-5991164

---------------

        1229792

 

redo size = 1229792 1M

 

 

 

2.归档模式下:segment FLM

 

SQL> create table my_objects tablespace HWM 

as select * from all_objects where rownum<20000;

 

Table created

 

SQL> delete from my_objects where object_name like '%C%';

 

7278 rows deleted

 

SQL> delete from my_objects where object_name like '%U%';

 

2732 rows deleted

 

SQL> commit;

 

Commit complete

 

SQL> select value from v$mystat, v$statname

where v$mystat.statistic# = v$statname.statistic# 

and  v$statname.name = 'redo size';

 

     VALUE

----------

   5929756

 

SQL> alter table my_objects move;

 

Table altered

 

SQL> select value from v$mystat, v$statname

where v$mystat.statistic# = v$statname.statistic# 

and  v$statname.name = 'redo size';

 

     VALUE

----------

   7146592

 

SQL> select 7146592 - 5929756 from dual;

 

7146592-5929756

---------------

        1216836

 

Redo size = 1216836 1M

我们发现,在归档模式下,segment不管是ASSM还是FLMmove产生的日志是一样多的。

 

3.非归档模式下:segment ASSM

 

SQL> create table my_objects  tablespace ASSM

as select * from all_objects where rownum<20000;

 

Table created

 

SQL> delete from my_objects where object_name like '%C%';

 

7278 rows deleted

 

SQL> delete from my_objects where object_name like '%U%';

 

2732 rows deleted

 

SQL> commit;

 

Commit complete

 

SQL> select value from v$mystat, v$statname

where v$mystat.statistic# = v$statname.statistic# 

and  v$statname.name = 'redo size';

 

     VALUE

----------

   3754152

 

SQL> alter table my_objects move;

 

Table altered

 

SQL> select value from v$mystat, v$statname

where v$mystat.statistic# = v$statname.statistic# 

and  v$statname.name = 'redo size';

 

     VALUE

----------

   4020876

 

SQL> select 4020876-3754152 from dual;

 

4020876-3754152

---------------

         266724

 

Redo size = 266724 250K

 

 

4.非归档模式下:segment FLM

 

SQL> create table my_objects tablespace HWM 

as select * from all_objects where rownum<20000;

 

Table created

 

SQL> delete from my_objects where object_name like '%C%';

 

7278 rows deleted

 

SQL> delete from my_objects where object_name like '%U%';

 

2732 rows deleted

 

SQL> commit;

 

Commit complete

 

SQL> select value from v$mystat, v$statname

where v$mystat.statistic# = v$statname.statistic# 

and  v$statname.name = 'redo size';

 

     VALUE

----------

   7747688

 

SQL> alter table my_objects move;

 

Table altered

 

SQL> select value from v$mystat, v$statname

where v$mystat.statistic# = v$statname.statistic# 

and  v$statname.name = 'redo size';

 

     VALUE

----------

   7829084

 

SQL> select 7829084 - 7747688  from dual;

 

7829084-7747688

---------------

          81396

 

Redo size = 81396  80K

 

通过这几个实验,我们发现,对table进行move操作时,在非归档模式下生成的redo size要比归档模式下少的多;非归档模式下,在FLM下比ASSM下生成的redo size也要少一些.

 

                    归档模式                   非归档模式

FLM               1M                       80K

ASSM             1M                       250K

5.我们再来看看在归档模式下table为nologging的情况,这里用FLM来测试:

SQL> create table my_objects tablespace HWM as select * from

all_objects where rownum<20000;

 

Table created

 

SQL> alter table my_objects nologging;

 

Table altered

 

SQL> delete from my_objects where object_name like '%C%';

 

7278 rows deleted

 

SQL> delete from my_objects where object_name like '%U%';

 

2732 rows deleted

 

SQL> commit;

 

Commit complete

 

SQL> select value from v$mystat, v$statname where v$mystat.statistic# = v$statname.statistic#  and  v$statname.name = 'redo size';

 

     VALUE

----------

  10874352

 

SQL> alter table my_objects move;

 

Table altered

 

SQL> select value from v$mystat, v$statname where v$mystat.statistic# = v$statname.statistic#  and  v$statname.name = 'redo size';

 

     VALUE

----------

  10955704

 

SQL> select 10955704-10874352 from dual;

 

10955704-10874352

-----------------

            81352

 

Redo size = 81352  80K

这时,redo size的生成量和非归档模式的FLM下一样了。

 

我们发现,table move操作生成的日志在归档和非归档模式以及nologging下的redo size的结果和insert append生成redo size的情况非常类似。

http://blog.youkuaiyun.com/dlinger/archive/ 2004/07/14 /41359.aspx

http://www.itpub.net/showthread.php?threadid=242761

关于moveshrink的日志生成对比,参见:

http://blog.youkuaiyun.com/dlinger/archive/ 2004/07/14 /41364.aspx

 

 

 

 

 

 

<think>我们正在开发一个Qt地图应用,需要实现鼠标点击自动连线的功能。根据用户需求,我们需要处理鼠标点击事件,记录点击的点位,并在这些点位之间绘制连线。同时,我们还需要考虑绘制的效率和实时显示。 参考引用内容: [^1] 提到了在绘制矩形时,通过鼠标事件记录起点和终点,并实时绘制矩形。类似地,我们可以通过鼠标按下事件记录点,并在移动过程中实时显示连线(如果需要预览),然后在鼠标释放时完成绘制。 [^2] 展示了一个使用Qt的鼠标事件处理来绘制连线的示例。它通过重写鼠标事件处理函数(如mousePressEvent, mouseMoveEvent, mouseReleaseEvent)来记录点并绘制。 [^3] 提到了路径规划中获取轨迹点并绘制,这可以借鉴如何将一系列点连成线。 [^4] 提供了绘制和擦除的方法,其中设置画笔和画刷的方法对我们绘制连线很有帮助。 [^5] 提到了动态显示线上点的值,虽然我们可能不需要显示值,但动态绘制连线可以参考。 实现思路: 1. 我们需要一个容器(如QVector<QPoint>)来存储用户点击的点。 2. 重写鼠标事件处理函数: - mousePressEvent: 当用户点击时,将点击的点(注意坐标转换,可能需要从屏幕坐标转换为地图坐标)添加到容器中,并触发更新绘制。 - mouseMoveEvent: 如果需要实时显示从最后一个固定点到当前鼠标位置的连线(即绘制过程中有预览线),则在此事件中记录当前鼠标位置并更新绘制。 - mouseReleaseEvent: 如果需要,可以在这里处理(但通常点击即确定点,所以可能不需要,除非是拖动确定点)。 - mouseDoubleClickEvent: 可以用于结束绘制(可选)。 3. 在paintEvent中,我们遍历存储的点,依次绘制连线。如果正在移动过程中(即预览状态),则还需要绘制从最后一个固定点到当前鼠标位置的线段。 步骤: 1. 创建一个自定义的Qt地图控件(例如继承自QWidget或QGraphicsView,根据地图框架选择)。 2. 在自定义控件中,声明成员变量: - QVector<QPoint> m_points; // 存储已确定的点 - QPoint m_currentPoint; // 当前鼠标位置(用于预览) - bool m_tracking; // 是否正在跟踪鼠标移动(用于预览) 3. 重写鼠标事件: - 在mousePressEvent中,如果是左键按下,则将点添加到m_points,并设置m_tracking为true(用于预览线)。 - 在mouseMoveEvent中,如果m_tracking为true,则更新m_currentPoint并触发重绘(update())。 - 在mouseReleaseEvent中,通常不需要,但如果是结束一个线段,可以在这里处理(但我们的需求是点击即确定点,所以通常不需要)。 - 另外,可以设置双击事件结束绘制:mouseDoubleClickEvent中,清空m_points,并重置状态(或者结束当前连线,开始新的路径)。 4. 在paintEvent中: - 首先,绘制地图(如果有)。 - 然后,绘制已确定的连线:遍历m_points,每两个相邻点之间绘制线段。 - 最后,如果m_tracking为true且m_points不为空,则绘制从m_points最后一个点到m_currentPoint的预览线。 注意:坐标转换。如果地图有缩放和平移,需要将鼠标的坐标转换为地图坐标。 代码结构示例(假设我们使用QWidget作为基类): 头文件(例如MapWidget.h): ```cpp #include <QWidget> #include <QVector> #include <QPoint> #include <QMouseEvent> class MapWidget : public QWidget { Q_OBJECT public: explicit MapWidget(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseDoubleClickEvent(QMouseEvent *event) override; private: QVector<QPoint> m_points; // 存储已确定的点 QPoint m_currentPoint; // 当前鼠标位置(用于预览) bool m_tracking; // 是否正在跟踪(预览状态) }; ``` 源文件(MapWidget.cpp): ```cpp #include "MapWidget.h" #include <QPainter> MapWidget::MapWidget(QWidget *parent) : QWidget(parent), m_tracking(false) { // 设置背景等 } void MapWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QPainter painter(this); // 1. 绘制地图背景(如果有) // ... // 2. 绘制已确定的连线 painter.setRenderHint(QPainter::Antialiasing, true); painter.setPen(QPen(Qt::blue, 2)); for (int i = 1; i < m_points.size(); ++i) { painter.drawLine(m_points[i-1], m_points[i]); } // 3. 绘制预览线(从最后一个确定的点到当前鼠标位置) if (m_tracking && !m_points.isEmpty()) { painter.setPen(QPen(Qt::blue, 2, Qt::DashLine)); painter.drawLine(m_points.last(), m_currentPoint); } } void MapWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { // 添加点 m_points.append(event->pos()); m_tracking = true; // 开始跟踪鼠标移动,用于预览 update(); // 触发重绘 } } void MapWidget::mouseMoveEvent(QMouseEvent *event) { if (m_tracking) { m_currentPoint = event->pos(); update(); // 实时更新预览线 } } void MapWidget::mouseDoubleClickEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { // 双击结束当前路径绘制,可以清空点或者做其他处理 m_points.clear(); m_tracking = false; update(); } } ``` 说明: 1. 上述代码实现了点击添加点,并绘制连线,移动鼠标时显示预览线,双击清空所有点。 2. 如果需要结束绘制(比如右键结束),可以添加mouseReleaseEvent处理右键事件,结束当前路径(不清空,但停止预览,直到重新开始)。 3. 坐标转换:上述代码直接使用event->pos(),这是相对于控件的位置。如果地图有缩放或平移,需要将鼠标位置转换为地图坐标。这需要根据地图的变换矩阵进行转换。 如果是在QGraphicsView中实现,可能需要重写QGraphicsView的鼠标事件,并在场景中添加QGraphicsLineItem等图元。但基本思路类似。 另外,参考[^4]中提到了设置画笔和抗锯齿,我们在paintEvent中已经设置了。还可以参考设置CompositionMode,但这里不需要擦除,所以不用设置。 性能考虑:如果点非常多,可以考虑使用QPainterPath来绘制路径,这样效率更高。 改进:使用QPainterPath存储路径,然后在paintEvent中绘制整个路径。 修改后的paintEvent: ```cpp void MapWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QPainter painter(this); // 绘制地图... // 绘制已确定的路径 painter.setRenderHint(QPainter::Antialiasing); QPen pen(Qt::blue, 2); painter.setPen(pen); // 使用QPainterPath绘制路径 QPainterPath path; if (!m_points.isEmpty()) { path.moveTo(m_points[0]); for (int i = 1; i < m_points.size(); ++i) { path.lineTo(m_points[i]); } } painter.drawPath(path); // 绘制预览线 if (m_tracking && !m_points.isEmpty()) { pen.setStyle(Qt::DashLine); painter.setPen(pen); painter.drawLine(m_points.last(), m_currentPoint); } } ``` 这样修改后,绘制效率会有所提高,特别是点很多的时候。 根据用户需求,我们实现了鼠标点击自动连线的功能。用户点击地图,程序记录点击的点并绘制连线,同时移动鼠标时显示预览线。 相关问题: 1. 如何实现带箭头的连线(比如表示方向)? 2. 如何保存绘制好的路径? 3. 如何实现撤销(Undo)和重做(Redo)功能?</think>### Qt地图界面中鼠标点击自动连线功能实现 在Qt地图应用中实现鼠标点击自动连线功能,需结合鼠标事件处理和图形绘制技术。以下是完整实现方案: #### 核心实现步骤 1. **创建自定义地图控件** ```cpp #include <QWidget> #include <QPainter> #include <QMouseEvent> #include <QVector> class MapWidget : public QWidget { Q_OBJECT public: explicit MapWidget(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent*) override; void mousePressEvent(QMouseEvent*) override; void mouseMoveEvent(QMouseEvent*) override; void mouseDoubleClickEvent(QMouseEvent*) override; private: QVector<QPointF> m_points; // 存储点击坐标 QPointF m_currentPos; // 当前鼠标位置 bool m_tracking = false; // 是否正在连线 }; ``` 2. **鼠标事件处理** ```cpp void MapWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { // 添加新点并开始跟踪 m_points.append(event->pos()); m_tracking = true; update(); // 触发重绘 } } void MapWidget::mouseMoveEvent(QMouseEvent *event) { if (m_tracking) { m_currentPos = event->pos(); update(); // 实时更新预览线 } } void MapWidget::mouseDoubleClickEvent(QMouseEvent*) { // 双击结束连线 m_points.clear(); m_tracking = false; update(); } ``` 3. **绘制连线路径** ```cpp void MapWidget::paintEvent(QPaintEvent*) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); // 1. 绘制已确定的线段 painter.setPen(QPen(Qt::blue, 2)); for (int i = 1; i < m_points.size(); ++i) { painter.drawLine(m_points[i-1], m_points[i]); } // 2. 绘制实时预览线 if (m_tracking && !m_points.isEmpty()) { painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); painter.drawLine(m_points.last(), m_currentPos); } } ``` #### 关键优化技术 1. **坐标转换**(地图坐标 ↔ 屏幕坐标) ```cpp // 实际项目中需添加坐标转换方法 QPointF MapWidget::screenToMap(const QPointF &screenPos) { return m_mapTransform.inverted().map(screenPos); } ``` 2. **高性能绘制**(针对大量线段) - 使用`QPainterPath`预编译路径 - 启用OpenGL加速(`QOpenGLWidget`) ```cpp // 在paintEvent中优化 QPainterPath path; if (!m_points.isEmpty()) { path.moveTo(m_points[0]); for (int i = 1; i < m_points.size(); ++i) { path.lineTo(m_points[i]); } painter.drawPath(path); } ``` 3. **触摸屏支持**(参考引用[^4]) ```cpp void MapWidget::mouseReleaseEvent(QMouseEvent *event) { if (event->source() == Qt::MouseEventSynthesizedBySystem) { // 触摸屏事件处理 } } ``` #### 完整工作流程 1. 用户点击地图 → 记录为路径起点 2. 鼠标移动 → 显示起点到当前位置的虚线预览 3. 再次点击 → 添加新顶点并绘制实线 4. 双击 → 清除当前路径 5. 右键 → 可添加删除顶点功能(需扩展实现) > **注意**:实际地图应用中需集成地图SDK(如QtLocation),将屏幕坐标转换为地理坐标,并处理地图缩放和平移时的坐标转换[^3]。 ### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值