을 증명하는 방법의 부족은 암시기 위해 데이터베이스에서?

최근 나를 설명하고 동료들의 중요성을 갖는 열의를 정렬 데이터를 데이터베이스 테이블에 필요한 경우를 이렇게 예를 들어,연대순으로 정렬된 데이터입니다. 이는 다소 어려울 수 있기 때문에 단순히 다시 실행하여 그들의 쿼리가 겉으로 끝없이 그것은 항상 동일한 세트의 행에서 같은 순서입니다.

내가 이것을 발견하기 전에와 모든 내가 정말 할 수 있는 주장 그들은 날 믿지 않는 단순히 가는 데이터베이스 테이블처럼 행동하는 전통적인 CSV 또는 Excel 파일입니다.

예를 들어,실행하(PostgreSQL)쿼리

create table mytable (
    id INTEGER PRIMARY KEY,
    data TEXT
);
INSERT INTO mytable VALUES
    (0, 'a'),
    (1, 'b'),
    (2, 'c'),
    (3, 'd'),
    (4, 'e'),
    (5, 'f'),
    (6, 'g'),
    (7, 'h'),
    (8, 'i'),
    (9, 'j');

테이블을 만들과 함께 지우기 위해 개념적. 선택하는 것과 동일한 데이터에서는 가장 간단한 방법이 될 것이다:

SELECT * FROM mytable;

항상 나에게 다음의 결과는:

 id | data 
----+------
  0 | a
  1 | b
  2 | c
  3 | d
  4 | e
  5 | f
  6 | g
  7 | h
  8 | i
  9 | j
(10 rows)

내가 이것을 할 수 있고 또 다시고 항상 내게로 돌아 같은 데이터와 같은 순서. 그러나 내가 알기에는 이를 암시적 위해 끊을 수 있는,내가 그것을 보았기 전에,특히 큰 데이터,어디서 어떤 임의의 값을 얻을 것이 분명히으로 던져"잘못"할 때 선택합니다. 하지만 그것이 나에게 발생하는't 알고 어떻게 이런 일이 발생 또는 어떻게 재현 합니다. 나는 그것을 찾기 어려운 결과를 얻을하기 때문에 Google 에서 검색하는 경향이 다시 일반에 대한 도움말 분류 결과를 설정합니다.

그래서 제 질문은 근본적으로 이러한:

  1. 는 방법은 명백하고 구체적으로 증명되는 반환하기 위해 행 쿼리에서없이위로문는 신뢰할 수 없습니다,바람직하게는 발생하여 보여주는 고장의 암시적 위는 경우에도 문제의 테이블이 업데이트 하지 않거나 편집?

  2. 그것은 어떤 차이가 모든 경우에만 데이터를 삽입 한 번에 한꺼번에 다음 없이 업데이트 again?

아 postgresql-기 때문에 대답을 하는데 익숙하지만 나는'm 에 더 관심이 있는 이론이다.

질문에 대한 의견 (7)

나는 세 가지 방법을 시도하여 그들을 설득:

  1. 해 최선을 다하고 동일한 쿼리와 더 테이블(더 많은 수의 행)또는 테이블이 업데이트되고 있 사이에 실행하고 있습니다. 거나 새로운 행을 삽입하고 일부 기존 삭제됩니다. 또는 인덱스에 추가되거나 사이에 실행하고 있습니다. 또는 테이블은 진공 청소기로 청소(에 Postgres). 또는 인덱스를 재 구축(에서 SQL Server). 또는 테이블이 변경에서 클러스터 힙. 또는 데이터베이스 서비스는 다시 시작됩니다.

  2. 당신은 제안할 수 있다는 것을 증명하는 다른 실행을 반환합니다 같은 순서입니다. 그들은 그것을 증명? 을 제공할 수 있는 일련의 테스트는 것을 증명한 것쿼리을 줄 것이다 그 결과 같은 순서 방법에 상관없이 여러 번 실행?

  3. 문서를 제공의 다양한 DBMS 에서는 문제입니다. 예를 들어:

[PostgreSQL][postgres]:

행 정렬

후에는 쿼리를 생산하고 있 출력 테이블의(선택한 후 목록을 처리했)할 수 있습니다. 는 경우에 정렬을 선택하지 않은 행 것에 반환되는 불특정다. 실제기 위해서는 경우따라 달라집에 검사 가입하세 계획의 유형과 주문에 디스크만 의존합니다. 특정한 출력은 주문이 수상하는 경우 이종 단계는 명시적으로 선택합니다.

SQL 서버:

선택-주문절(Transact-SQL)

종류에 의해 반환되는 데이터는 다음을 수행할 수 있습니다 이 절을 사용하여하기:

기 위해 그 결과를 설정하여 쿼리의 지정된 열 목록 및 필요에 따라 제한이 반환한 행하여 지식이 요구됩니다. 순서는 반환되는 행 결과에 설정되지 않은 보장하지 않으면주문절을 지정합니다.

[Oracle][oracle]:

order_by_clause

사용하여 순서`절하기 위해 행 반환되는 문입니다. 없이 order_by_clause,없음을 보증 존재하는 같은 쿼리가 실행되는 두 번 이상이 검색 행 같은 순서.

해설 (8)

이것은 검은 백조는 이야기다. 지 않은 경우에는't 하나 아직 보지 않't mean they don't 존재합니다. 희망이 귀하의 경우에는 그't 질을 다른 넓은 세계 금융위기,단순히 몇 가지 고객 불만족.

Postgres문서를 말한다명시적으로:

If 순서에 의해 주어지지 않는 행은 반환되는 순서와 상관없이 시스템을 발견한 가장 빠르게 생산합니다.

"시스템"이 경우에 포함 postgres 데몬이 자체(의 구현을 포함하여 해당 데이터에 액세스 방법 및 쿼리 최적화 프로그램),기존 운영 체제,논리적이고 물리적 레이아웃의 데이터베이스에 저장 가능,심지어 CPU 캐시합니다. 이후 데이터베이스는 사용자를 제어 할 수 없는 스택해야에 의존하지 않을 계속 행동이 영원히 작용하는 방식이다.

동료들을 투입하고 있다성급 일반화 착오. 반는 자신의 포인트에 충분하다는 자신의 가정은 잘못된 단 한번만,예를 들어이 dbfiddle.

해설 (0)

다음 예제를 고려해,우리가 세과 관련된 테이블이 있습니다. 주문,사용자와 OrderDetails. OrderDetails 과 연결된 외국의 열쇠를 주문 테이블과 사용자의 테이블. 이것은 근본적으로 매우 전형적인 설정을 관계형 데이터베이스를 틀림없이 전체의 목적관계DBMS. 사용 tempdb; 는 경우 OBJECT_ID(N&#39;dbo.OrderDetails&#39;,N&#39;U&#39;)을 NULL 이 아닌 테이블 삭제 dbo.OrderDetails; 는 경우 OBJECT_ID(N&#39;dbo.주문&#39;,N&#39;U&#39;)을 NULL 이 아닌 테이블 삭제 dbo.주문 는 경우 OBJECT_ID(N&#39;dbo.사용자는&#39;,N&#39;U&#39;)을 NULL 이 아닌 테이블 삭제 dbo.사용자; CREATE TABLE dbo.주문 ( 십시오 int NOT NULL 제약 OrderTestPK 기본 키가 클러스터 ,SomeOrderData varchar(1000) 제약 Orders_somedata_df 기본(CRYPT_GEN_RANDOM(1000)) ); CREATE TABLE dbo.사용자 ( UserID int NOT NULL 제약 UsersPK 기본 키가 클러스터 ,SomeUserData varchar(1000) 제약 Users_somedata_df 기본(CRYPT_GEN_RANDOM(1000)) ); CREATE TABLE dbo.OrderDetails ( OrderDetailsID int NOT NULL 제약 OrderDetailsTestPK 기본 키가 클러스터 십시오 int NOT NULL 제약 OrderDetailsOrderID 외국 열쇠 참조 dbo.주문(십시오) 사용 int NOT NULL 제약 OrderDetailsUserID 외국 열쇠 참조 dbo.사용자는(UserID) ,SomeOrderDetailsData varchar(1000) 제약 OrderDetails_somedata_df 기본(CRYPT_GEN_RANDOM(1000)) ); 에 삽입 dbo.주문(십시오) 선택 최고(100)그룹()이상(순서로(선택 NULL)) Sys.syscolumns sc; 에 삽입 dbo.사용자는(UserID) 선택 최고(100)그룹()이상(순서로(선택 NULL)) Sys.syscolumns sc; 에 삽입 dbo.OrderDetails(OrderDetailsID 십시오 UserID) 선택 최고(10000)그룹()이상(순서로(선택 NULL)) o.십시오 u.UserID Sys.syscolumns sc 크로스 가입하세 dbo.주문 o 크로스 가입하세 dbo.사용자는 u 주문십시오(); CREATE INDEX OrderDetailsOrderID 에 dbo.OrderDetails(십시오); CREATE INDEX OrderDetailsUserID 에 dbo.OrderDetails(UserID); 여기,우리는'시를 쿼리하 OrderDetails 테이블 UserID15: 선택 od.OrderDetailsID o.십시오 u.UserID 에서 dbo.OrderDetails od 내부 조 dbo.사용자는 u u.UserID=od.UserID 내부 조 dbo.주문 o 에 od.십시오=o.십시오 는 u.UserID=15 출력에서 쿼리는 다음과 같: <전> ╔════════════════╦═════════╦════════╗ ║OrderDetailsID║십시오║UserID║ ╠════════════════╬═════════╬════════╣ ║2200115║2║15║ ║630215║3║15║ ║1990215║3║15║ ║4960215║3║15║ ║100715║8║15║ ║3930815║9║15║ ║6310815║9║15║ ║4441015║11║15║ ║2171315║14║15║ ║3431415║15║15║ ║4571415║15║15║ ║6421515║16║15║ ║2271715║18║15║ ║2601715║18║15║ ║3521715║18║15║ ║221815║19║15║ ║3381915║20║15║ ║4471915║20║15║ ╚════════════════╩═════════╩════════╝</전> 당신이 볼 수 있듯이,순서 행 출력이 일치하지 않기 위해 행 OrderDetails 테이블에서. 추가 명시적인주문에 의해 보장하는 행환 클라이언트에서 원하는 순서는: 선택 od.OrderDetailsID o.십시오 u.UserID 에서 dbo.OrderDetails od 내부 조 dbo.사용자는 u u.UserID=od.UserID 내부 조 dbo.주문 o 에 od.십시오=o.십시오 는 u.UserID=15 주문 od.OrderDetailsID; <전>╔════════════════╦═════════╦════════╗ ║OrderDetailsID║십시오║UserID║ ╠════════════════╬═════════╬════════╣ ║3915║40║15║ ║100715║8║15║ ║221815║19║15║ ║299915║100║15║ ║368215║83║15║ ║603815║39║15║ ║630215║3║15║ ║728515║86║15║ ║972215║23║15║ ║992015║21║15║ ║1017115║72║15║ ║1113815║39║15║ ╚════════════════╩═════════╩════════╝</전> 경기의 행은 필수적이,그리고 엔지니어가 알기 위해 필수적이,그들은 단지원하는를 사용한주문구문 때문에,그 비용이 있습니다 그들에게 그들의 지정에 오류가 발생한 경우 관련하여 잘못된 순서입니다. 두 번째는,아마도 더 교훈이 있을 사용하여,OrderDetails테이블 위에서,우리는'시하지*가 다른 어떤 테이블,하지만 간단한 요구 사항을 찾아 행은 일치하는 두십시오와 이용자 Id,우리는 문제입니다. 우리는'll 인덱스 생성을 지원하는 쿼리를 같이 실생활에서 수행하는 경우 성능이 어떤 방법으로 중요하다(때 아't it?). CREATE INDEX OrderDetailsOrderIDUserID 에 dbo.OrderDetails(십시오 UserID); 여기's 쿼리: 선택 od.OrderDetailsID 에서 dbo.OrderDetails od 는 od.십시오=15 고(od.UserID=21od.UserID=22) 그 결과는: <전> ╔════════════════╗ ║OrderDetailsID║ ╠════════════════╣ ║21421║ ║5061421║ ║7091421║ ║691422║ ║3471422║ ║7241422║ ╚════════════════╝</전> 추가 있는주문절은 가장 확실히 보장하는 올바른 정렬합니다. 이러한 모형은 간단한 예제는 행성이 보장되지 않으며"in order"지 않고 명시적인주문문입니다. 거기에 더 많은 예제는 다음과 같이,그리고 그 이후 DBMS 엔진 코드 변경을 매우 자주,특정한 행위가 시간에 따라 변경될 수 있습니다.

해설 (0)

실질적인 예로서,Postgres,주문 현재의 변화를 업데이트하는 경우 줄:

% SELECT * FROM mytable;
 id | data 
----+------
  0 | a
  1 | b
  2 | c
  3 | d
  4 | e
  5 | f
  6 | g
  7 | h
  8 | i
  9 | j
(10 rows)

% UPDATE mytable SET data = 'ff' WHERE id = 5;
UPDATE 1
% SELECT * FROM mytable;
 id | data 
----+------
  0 | a
  1 | b
  2 | c
  3 | d
  4 | e
  6 | g
  7 | h
  8 | i
  9 | j
  5 | ff
(10 rows)

I don't 생각의 규칙이 기존하는 암시를 주문서 설명하는 곳은 확실히 예고없이 변경 될 수 있고 확실히 휴대용하지 않는 행동에 걸쳐 DB 엔진이 있습니다.

해설 (2)

정확하지 않지만 너무 길어 있습니다.

대형 테이블에 일부 데이터베이스는 할 것이다 인터리브 병렬로 검색:

두 경우 쿼리를 검색하려는 동일한 테이블 및 도착하는 거의 같은 시간에,최초의 일부가 될 수도 있습 방법을 통해 표면 두 번째 시작됩니다.

두 번째는 쿼리를 받을 수 있는 레코드에서 시작하는 테이블의 중간(처음으로 쿼리가 완료)을 받을 수 있는 레코드의 시작에서는 테이블.

해설 (0)

성을 클러스터 된 인덱스"잘못"순서입니다. 예를 들어,클러스터에ID DESC. 이것은 자주 출력 반전 주문(지만 이것은 보장하지 않나).

해설 (0)