我想知道什么时候在相对较大的表(几百 GB)上重建 BTree 索引才有意义。
对我来说,任何高于 30% 或 40% 的值似乎都是不错的候选者,但我看到有人说即使 70% 对于 Postgres 来说也不算太糟糕。pgstattuple.pgstatindex
如果重要的话,我会从功能中得到碎片。
我想知道什么时候在相对较大的表(几百 GB)上重建 BTree 索引才有意义。
对我来说,任何高于 30% 或 40% 的值似乎都是不错的候选者,但我看到有人说即使 70% 对于 Postgres 来说也不算太糟糕。pgstattuple.pgstatindex
如果重要的话,我会从功能中得到碎片。
我想知道为什么这两个查询的执行计划成本不同:
create table test_insert(id int not null primary key, value varchar2(10));
--1
insert into test_insert(id,value)
values (2,'111');
--2
insert into test_insert(id,value)
select 3,'111' from dual where not exists (select null from test_insert where id =3);
查询 2 的成本总是更高(多少取决于表中的行数)。根据我的理解not exits ...
,不应增加任何开销——为了强制执行 PK 约束,引擎无论如何都必须检查相应的唯一索引,因此子查询会增加额外的解析时间,但不会增加执行时间或计划的额外步骤。
该示例适用于 Oracle,但我也检查了 Postgres,结果相似。
例如,
--1
| Id | Operation | Name | Cost |
--------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 |
| 1 | LOAD TABLE CONVENTIONAL | TEST_INSERT | |
--------------------------------------------------------
--2
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | | | 3 (100)| |
| 1 | LOAD TABLE CONVENTIONAL | TEST_INSERT | | | | |
|* 2 | FILTER | | | | | |
| 3 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | SYS_C0012345 | 1 | 13 | 1 (0)| 00:00:01 |
我想知道是否可以在不对依赖对象进行级联类型更改的情况下重命名 Postgres 表?例如,
create table test_1(id int);
create function test_1_funct (param test_1[]) returns void as $body$
begin
return;
end
$body$
language plpgsql;
alter table test_1 rename to test_2 ;
-- function test_1_funct signature silently changed,
-- so it now accepts test_2[].
我想模拟类似于 Oracle 所做的行为 - 将函数标记为无效,让我使用旧名称创建表,然后根据需要重新编译该函数。事实上,它不允许我drop table test_2
。
我环境中的一个物理备用数据库以只读模式打开并用于报告目的。
我只想让用户访问这个特定的备用数据库,而不是主数据库。
到目前为止,我发现的最佳方法是创建AFTER LOGON ON DATABASE
触发器来检查v$instance
(或可能),并根据/ columnsv$database
的值抛出错误。host_name
instance_role
我想知道是否有更好的方法来做到这一点。
是否可以在SQL Server 2008 中模仿OracleSET AUTORECOVERY ON
来应用事务日志?
RESTORE LOG [DB_NAME] FROM DISK
需要备份名称;如果我有几百个日志,我必须确保日志以正确的顺序恢复。当然,我可以按名称对文件进行排序,但我想知道是否有开箱即用的解决方案。
谢谢你。
例如(只是为了说明问题),
CREATE TABLE test_join(ID INT NOT NULL);
--1
SELECT ID FROM
test_join A
INNER JOIN test_join b ON 1=1;
--2
SELECT ID FROM
test_join A
INNER JOIN test_join b ON 1=1
INNER JOIN test_join c ON 1=1;
第一个给出预期的“ORA-00918:列定义不明确”。第二个执行没有任何投诉(Oracle 10g)。我想知道这是一个错误还是我在名称解析规则中遗漏了一些明显的东西。Oracle 11 在这两种情况下都给出了错误。
谢谢
碰巧我不得不同时使用 SQL Server 和 Oracle 很长一段时间(幸好不是同时使用)。
仍然让我感到困惑的是将表格存储为平衡树的方法。在类似 Oracle 的 RDMS 中,堆是默认的,在 SQL Server(和许多其他)中,相反(集群,IOT)是正确的。每种方法的专家都声称他们的方法是唯一“正确”的方法,并通过一堆测试/演示来支持选择的观点。但是,在我看来,他们证明的唯一一点是“非默认”方法的实施很差,并且不应该在大多数情况下使用......
我很确定这两种方法都足够好(只是因为它们仍然存在于市场上并且表现出可比的性能)并且在下面有一些数学,但我没有找到任何好的参考。
我意识到这个话题可能过于宽泛而无法回答,并且非常欢迎良好的链接,但我真的很想知道为什么两种看似有争议的方法已经证明它们都是有效的。
我正在将数据库从 Oracle 移动到 SQLServer(如果重要,则为 2012 年)。迁移表/视图的过程或多或少是直接和自动化的。触发器也不是问题,因为我没有太多触发器。
但是,我想知道移动 Oracle 包的最佳实践是什么。据我所知,SQLServer 没有类似的东西。我的想法是将每个包映射到 SQLServer 模式(例如,我将在 SQLServer 中有 'package1' 、 'package2' 等模式,它们每个都没有表,只有函数/过程/类型)。我相信它将保留软件包的原始用途,同时减少应用程序方面所需的更改数量。
这有意义还是我走错了路?
谢谢你。
我有一个死锁问题,可以通过更改应用程序逻辑轻松解决,但我的印象是 Oracle 的行为会有所不同,而且死锁永远不会发生。例如我有两张桌子
table1( table1_id (PK), num1, num2);
table2(table2_id(PK), table1_id(FK to table1,indexed), low_cardinality_column, num3, num4);
Table2 也有更新( ) 的行级after update
触发器。table1.num
table1.num1 = table1.num1 + :NEW.num3 where table1.table1_id = :NEW.table1_id
第一个进程执行UPDATE table2 set num3 =1 where low_cardinality_column =:bind_var
(没有索引low_cardinality_column
,通常影响数千条记录)。
第二个进程在一个事务中更新 table2 和 table1
UPDATE table2
SET num4 = :bind_var4
WHERE table2_id = :bind_var_id
RETURNING table1_id INTO :out_var
UPDATE table1
SET num2 = :new_num2_val
WHERE table1_id = :out_var
如果这两个进程碰巧同时运行,Trace 显示它们之间存在相当多的死锁,我对此感到有点困惑。table1
我知道如果第二个过程以相反的顺序更新表( ,然后),那么一定会发生死锁table2
,但在这种特殊情况下,我认为引擎实际上不会开始更新,直到它在每个必须更新的记录上获得 RX 锁(因此一个进程会等待另一个进程完成)。如果不能保证,那么死锁的解释是显而易见的:进程 1 以未定义的顺序锁定记录,进程 2 碰巧更新了table2
尚未锁定的行并尝试更新table1
进程 1 已更新的行。对于 SQLServer I会 100% 肯定是这种情况,但我对 Oracle 还是很陌生......
我想知道是否有人可以澄清这个问题。谢谢你。如果重要的话,我使用 10g。
假设我有以下程序
CREATE PROCEDURE foo (table1_id IN TABLE1.table1_id%type,
table1_val IN TABLE1.table1_value%type)
AS
SQL_UPDATE VARCHAR2(500) := 'UPDATE TABLE1 SET table1_value =:1 WHERE table1_id = :2';
BEGIN
--.....
--1 :
EXECUTE IMMEDIATE SQL_UPDATE USING foo.table1_val, foo.table1_id;
--2 :
UPDATE TABLE1 SET table1_value = foo.table1_val WHERE table1_id = foo.table1_id;
END;
除了样式/可读性之外,在这种情况下(我的意思是当它绝对可以避免时)与(2)相比,使用动态查询(1)是否有任何性能损失?
谢谢你。
我表中的一列存储以逗号分隔的值列表(我知道这是一个糟糕的设计,但目前不能进行重构)。我似乎想出了一个可行的解决方案,但恐怕效率不高:
select distinct test_id , regexp_substr(str_data,'[^,]+', 1, level)
from
(
select 1 as test_id, '1,2,3' as str_data from dual
union all
select 2 as test_id, '4,5,6' as str_data from dual
)test_data
connect
by
regexp_substr(str_data, '[^,]+', 1, level) is not null
我不喜欢我必须使用distinct
. 有更好的方法吗?
谢谢你。
我有一个收集对象的存储过程。( TABLE OF MyCustomType
)。在过程中,我试图将此参数与真实表连接起来。
例如,像
create or replace TYPE MYTYPE AS OBJECT (....);
CREATE OR REPLACE TYPE LIST_OF_MYTYPE AS TABLE OF MYTYPE;
CREATE PROCEDURE FOO(my_table LIST_OF_MYTYPE ,....) AS
CURSOR cur_read_data IS
SELECT a.col1, b.col2, b.col3
FROM
TABLE(FOO.my_table) a
INNER JOIN existing_table b ON (b.existing_table_id = a.existing_table_id)
--b.existing_table_id - primary key supported by unique index
ORDER BY a.existing_table_id
;
BEGIN
FOR record_info in cur_read_data
LOOP
......
END LOOP;
END;
它有效,但我有一个性能问题。传递给过程的集合参数没有很多元素;即使它只有一个元素,执行计划也会涉及对existing_table
.
在 1 个元素的情况下,更改INNER JOIN existing_table b ON (b.existing_table_id = a.existing_table_id)
为INNER JOIN existing_table b ON (b.existing_table_id =FOO.my_table(1).existing_table_id )
会产生巨大的差异 - 查询使用“INDEX UNIQUE SCAN”,正如我在初始查询中所期望的那样。我什至尝试过没有结果的查询提示(有序,领先)......
即使我的应用程序中集合中的元素数量在 1 到 5 之间,并且可以编写一个过程的 5 个不同版本,我想知道是否可以使其按预期工作。
为了测试,我也做了
CURSOR cur_read_data IS
SELECT a.col1, b.col2, b.col3
FROM
(
SELECT 1 as existing_table_id, 'test 1' as col1 FROM DUAL
UNION
SELECT 2 as existing_table_id, 'test 2' as col1 FROM DUAL
UNION
SELECT 3 as existing_table_id, 'test 3' as col1 FROM DUAL
)
a
INNER JOIN existing_table b ON (b.existing_table_id = a.existing_table_id)
--b.existing_table_id - primary key supported by unique index
ORDER BY a.existing_table_id
这样它也可以按预期工作,INDEX_UNIQUE_SCAN,而不是全扫描......
感谢您的回答。
更新 相当令人惊讶,但将其重写为
CURSOR cur_read_data IS
WITH CTE1 AS (SELECT * FROM TABLE(FOO.my_table))
SELECT a.col1, b.col2, b.col3
FROM
CTE1 a
INNER JOIN existing_table b ON (b.existing_table_id = a.existing_table_id
AND b.existing_table_id IN (SELECT existing_table_id FROM CTE1))
ORDER BY a.existing_table_id
成本降低了大约 30 倍(1200 原始版本与 38 版本WITH
)这是可以接受的,但我仍然不知道为什么这有帮助......
另一个更新
分析V$SQLSTATS
表明,对于游标的第一个版本,它不惜一切代价避免 DISK READS (0),DIRECT WRITES 也是 0;使用WITH
以某种方式更改执行计划导致 CPU TIME 的巨大改进超过增加的 DISK READS (1)...
我想知道重新编译由于其中一个更改而变得无效的 Oracle 10g 可编程对象的最佳实践是什么。
更具体地说,我有一些使用模式级别类型的包。我在系统中也有从包中调用函数/过程的触发器。据我了解,包主体的更改不需要任何进一步的操作(重新编译主体除外)。但是,如果我更改 package ,我必须重新编译使用这个包的触发器以及其他依赖于它的包。
到目前为止,我只是抓取了无效对象的列表并重新编译它们或使用了 DBMS_UTILITY.compile_schema。
谢谢你。
我有下表:
CREATE TABLE action (action_id INT NOT NULL,
action_type_id INT NOT NULL,
action_date DATE NOT NULL);
CREATE INDEX IDX_ACTION_ACT_TYPE_ACT ON action(action_id, action_type_id);
ALTER TABLE action ADD CONSTRAINT PK_ACTION PRIMARY KEY (action_id)
USING INDEX IDX_ACTION_ACT_TYPE_ACT;
ALTER TABLE action ADD CONSTRAINT UQ_ACTION UNIQUE (action_id,action_type_id)
USING INDEX IDX_ACTION_ACT_TYPE_ACT;
-- I think the line below is irrelevant in the context of my question, but
-- in case I'm wrong...
ALTER TABLE action ADD CONSTRAINT FK_action_type_id FOREIGN KEY(action_type_id)
REFERENCES action_type(action_type_id);
-- Since action_type is a lookup added for normalization sake with no updates/deletes,
-- I don't see any value in having an index on FK column.
它是许多明细表的公共父表,这些明细表存储特定操作的额外信息。action_type_id
是唯一约束的一部分,让详细表具有 FK 到 (action_id,action_type_id) 并强制每个详细表只存储它应该存储的信息。
我想知道与创建 2 个索引相比,在 2 个约束中使用相同的索引是否有任何性能损失......在我看来它应该比 2 个索引表现得更好,但也许我遗漏了一些东西。如果重要的话,我正在使用 Oracle 10g。
谢谢您的回答。
假设我有下表:
CREATE TABLE test(test_id int not null identity primary key,
field1 int not null,
field2 int
);
CREATE INDEX IDX_test_field1 ON test(field1);
CREATE INDEX IDX_test_field2 ON test(field2);
现在ALTER TABLE test ALTER COLUMN field1 int
工作,并field1
允许null
.
然而,我无法改变ALTER TABLE test ALTER COLUMN field2 int not null
,因为
ALTER TABLE ALTER COLUMN field2 失败,因为一个或多个对象访问此列。
另外,我无法更改field1
回not null
.
但是,我可以根据需要多次添加然后删除检查约束:
ALTER TABLE test ADD CONSTRAINT CHK_NN_field2 CHECK (field2 IS NOT NULL);
DROP CONSTRAINT CHK_NN_field2` without any problems.
它是明确定义的行为吗?有人可以解释为什么会发生这种情况或指向我的文档吗?
如果这很重要,我正在使用 SQL Server 2008 R2。
谢谢你。
我在尝试让我的存储过程使用时遗漏了一些东西EXECUTE AS
。存储过程从 读取数据source_db
、聚合数据并将结果存储在target_db
.
sp 本身在target_db
. 我有一个专用的登录名并将其映射到sp 所有者的用户(因此在loginsource_db
和in 中有一个用户)。target_db
app_agent
source_db
target_db
app_agent
如果我以 身份登录app_agent
并执行
EXEC target_db.app_agent_schema.import_data
一切正常。但如果我改变
ALTER PROCEDURE app_agent_schema.import_data WITH EXECUTE AS OWNER` (or `AS SELF`)
并尝试执行它,它会抛出
服务器主体“app_agent”无法在当前安全上下文下访问数据库“source_db”。
我正在使用 SQL Server 2008。
有人可以指出我的错误吗?
谢谢
更新
在做了一些研究之后,我发现这ALTER DATABASE target_db SET TRUSTWORTHY ON
可以解决问题,但这对我来说似乎不是正确的解决方案......
我无法弄清楚为什么以下内容无法正常工作:
CREATE TABLE table1(table1_id INT NOT NULL PRIMARY KEY,
col1 INT NOT NULL,
val1 VARCHAR(50));
CREATE INDEX IDX_table1_fnct ON table1(CASE WHEN col1 = 3 THEN val1 ELSE NULL END);
SELECT COUNT(val1) WHERE col1 = 3 ; shows full scan
我希望新索引用于此类查询,但即使我试图用INDEX
提示强制它也不是......任何人都可以解释为什么它以这种方式工作(如果重要的话我正在使用 Oracle 10)?
谢谢
我想知道SELECT ... FOR UPDATE
在游标中使用时是否保证记录的锁定顺序?例如,
DECLARE
CURSOR test_cursor IS
SELECT field1, field2
FROM table1
ORDER BY pk_field
FOR UPDATE OF field1;
当我打开这样的游标时,它是否总是按顺序锁定记录pk_field
?
从我目前读到的内容来看,常规的锁定顺序不能保证SELECT ... ORDER BY pk_field FOR UPDATE
,但我不确定游标是否正确。我希望它确实锁定了ORDER BY
游标子句中设置的顺序;但是,我找不到确认。
谢谢你。
对于返回当前会话中是否有任何活动事务的查询,
SELECT COUNT(*)
FROM
v$transaction t
INNER JOIN v$session s ON (t.ses_addr = s.saddr )
INNER JOIN v$mystat m ON (s.sid = m.sid )
WHERE ROWNUM = 1;
EXPLAIN
显示0成本。然而,事实似乎并非如此。在高负载环境中定期运行此查询会导致服务器浪费几乎所有资源。
估计此类查询影响的正确方法是什么(我相信同样的问题不仅发生在这个特定的查询上,而且发生在涉及系统视图的任何事情上)?
谢谢。
如果问题标题含糊不清,我深表歉意,但我无法更好地表述它。我想要的是 TSQL 的替代方法CREATE TYPE
,因此我可以在列定义中使用它。
例如,我需要 Oracle 中的“money”类型,这在技术上是NUMBER(18,4)
在我的系统中,并且每个表都会有“money”列而不是底层NUMBER
以保持一致性。还有一些其他“类型”我想有别名而不是直接使用它们。
不幸的是,我还没有找到可接受的解决方案,除了放弃并为每列使用具有约束(或大小规范)的标准类型。似乎唯一可行的方法是创建OBJECT
类型,但它会为我试图避免的系统增加不必要的复杂性。
一个非常好的 Oracle 特性,SUBTYPE
在这种情况下不起作用。据我所知,SUBTYPE
(和来自 的子类型STANDARD
)创建了不能在 SQL 中使用的 PL/SQL 数据类型。我知道这有多种原因。
我想知道解决此类问题的最佳做法是什么。
谢谢你。
更新
到目前为止,我似乎已经列出了所有可能的方法,我宁愿关闭这个问题。不确定它是否对任何人有用;如果是,我暂时不删除这个问题。