gpt4 book ai didi

sql - 一个表怎么会违反它自己的主键索引呢?

转载 作者:行者123 更新时间:2023-11-29 11:25:05 26 4
gpt4 key购买 nike

我有一个 PostgreSQL 数据库,它有一个主键应用于三列的表。根据数据库,键上有一个索引:

Indexes:
"full_log_pkey" PRIMARY KEY, btree (server_name, line_number, log_generation)

然而一些简单的测试表明我有重复的键:

select count(*) from full_log;
count
----------
60644405

select count(*) from
(select distinct server_name,
line_number,
log_generation
from full_log) as foo;
count
----------
60636564

很明显,不同的行(基于主键)比行数少。我的问题是,这怎么可能?

编辑:完整的表定义是这样的:

                 Table "public.full_log"
Column | Type | Modifiers
----------------+-----------------------------+-----------
activity | character(1) |
archivaldate | timestamp without time zone |
media_type | character varying(5) |
vsn | text |
archive_set | character varying(20) |
copy | smallint |
file_start | integer |
file_offset | integer |
fs_name | character varying(20) |
inode | double precision |
file_length | bigint |
file_type | character(1) |
overflow | integer |
device_number | integer |
server_name | text | not null
path | text |
line_number | integer | not null
log_generation | integer | not null
Indexes:
"full_log_pkey" PRIMARY KEY, btree (server_name, line_number, log_generation)
Foreign-key constraints:
"full_log_server_name_fkey" FOREIGN KEY (server_name) REFERENCES servers(server_name)
Rules:
insert_update_full_log AS
ON INSERT TO full_log
WHERE (EXISTS ( SELECT full_log.activity, full_log.archivaldate, full_log.media_type, full_log.vsn, full_log.archive_set, full_log.copy, full_log.file_start, full_log.file_offset, full_log.fs_name, full_log.inode, full_log.file_length, full_log.file_type, full_log.overflow, full_log.device_number, full_log.server_name, full_log.path, full_log.line_number, full_log.log_generation
FROM full_log
WHERE full_log.server_name = new.server_name AND full_log.line_number = new.line_number AND full_log.log_generation = new.log_generation)) DO INSTEAD UPDATE full_log SET activity = new.activity, archivaldate = new.archivaldate, media_type = new.media_type, vsn = new.vsn, archive_set = new.archive_set, copy = new.copy, file_start = new.file_start, file_offset = new.file_offset, fs_name = new.fs_name, inode = new.inode, file_length = new.file_length, file_type = new.file_type, overflow = new.overflow, device_number = new.device_number, path = new.path
WHERE full_log.server_name = new.server_name AND full_log.line_number = new.line_number AND full_log.log_generation = new.log_generation

以重复行为例:

 select * from full_log where line_number = 6332986;
activity | archivaldate | media_type | vsn | archive_set | copy | file_start | file_offset | fs_name | inode | file_length | file_type | overflow | device_number | server_name | path | line_number | log_generation
----------+---------------------+------------+--------+-------------+------+------------+-------------+---------+------------+-------------+-----------+----------+---------------+-------------+-------------------------------------------------------------------------------------------+-------------+----------------
A | 2010-10-13 10:49:49 | ti | Z00711 | lcbp_rel | 1 | 226237 | 779099 | lcbp | 21798068.3 | 31198108 | f | 0 | 8511 | redact | wdl/delivery/irishparis_2010_09/MSE2_Histoire des rois d'Angleterre/MSE2_239.TIF | 6332986 | 1
A | 2010-10-13 10:49:49 | ti | Z00711 | lcbp_rel | 1 | 226237 | 779099 | lcbp | 21798068.3 | 31198108 | f | 0 | 8511 | redact | wdl/delivery/irishparis_2010_09/MSE2_Histoire des rois d'Angleterre/MSE2_239.TIF | 6332986 | 1
(2 rows)

最佳答案

这个查询返回什么?

select server_name, line_number, log_generation 
from full_log
group by server_name, line_number, log_generation
having count(*) > 1

将其与

进行比较可能会有所帮助
select line_number, log_generation 
from full_log
group by line_number, log_generation
having count(*) > 1

但它可能不会。我认为这个条款

WHERE (EXISTS ( SELECT full_log.activity, 
full_log.archivaldate,
full_log.media_type,
full_log.vsn,
full_log.archive_set,
full_log.copy,
full_log.file_start,
full_log.file_offset,
full_log.fs_name,
full_log.inode,
full_log.file_length,
full_log.file_type,
full_log.overflow,
full_log.device_number,
full_log.server_name,
full_log.path,
full_log.line_number,
full_log.log_generation
FROM full_log
WHERE full_log.server_name = new.server_name
AND full_log.line_number = new.line_number
AND full_log.log_generation = new.log_generation))

可以简化为这个子句。 (虽然我认为这不会导致问题。)

WHERE (EXISTS ( SELECT full_log.server_name, 
full_log.line_number,
full_log.log_generation
FROM full_log
WHERE full_log.server_name = new.server_name
AND full_log.line_number = new.line_number
AND full_log.log_generation = new.log_generation))

您说过当您更改非键列的数据类型时,PostgreSQL 会删除并重新创建索引。我在这里看不到这种情况,我不确定我是否见过这种情况。如果更改成功,我可能没有注意到,而且我不会定期更改列的数据类型。 (现在我已经说过了,我无法开始告诉你我上次这样做的时间。)我现在在这里有 PostgreSQL 9.0.2。

关于sql - 一个表怎么会违反它自己的主键索引呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5759588/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com