programing

mysql의 결정론적 함수

yellowcard 2023. 9. 17. 12:13
반응형

mysql의 결정론적 함수

저는 겉보기에는 단순한 개념과 혼동을 했습니다.Mysql은 결정론적 함수를 다음과 같은 함수로 정의합니다.

항상 동일한 입력 매개변수에 대해 동일한 결과를 생성합니다.

그래서 제가 알기로는 다음과 같은 기능을 합니다.

CREATE FUNCTION foo (val INT) READS SQL DATA
BEGIN
   DECLARE retval INT;
   SET retval = (SELECT COUNT(*) FROM table_1 WHERE field_1 = val);
   RETURN retval;
END;

결정적이지 않습니다(기능에 대한 두 호출 사이에 삭제/업데이트/삽입이 발생하지 않는다는 보장은 없습니다). 저는 에 따른 즉을 하는 ,에,는,의,즉,에,한,환,했습니다,이,고,과,을,의,은,들,을,는,은,했습니다,s,t,이,과,h,고,에,i,e,s,,,e,,,e,,,e,y,y,DETERMINISTIC기본적인 있는 것 . 제가 아주 기본적인 것을 놓치고 있는 것 같습니다.

누가 이 문제를 해명해 줄 수 있습니까?

감사해요.

업데이트 (+1)이라고 대답해주신 분들께 감사드립니다. 지금까지 의 오용이 널리 확산되고 있는 으로 보입니다.DETERMINISTIC 이 믿기 다른 답변을 이렇게 많은 분들이 하신다는 것이 아직 저로서는 믿기 힘들기 때문에 다른 답변을 조금 기다리겠습니다.

MySQL 5.0 참조:

루틴의 특성에 대한 평가는 제작자의 "정직함"에 근거합니다.MySQL은 DECIALSTIC으로 선언된 루틴이 비결정적인 결과를 생성하는 문이 없음을 확인하지 않습니다.그러나 루틴을 잘못 선언하면 결과에 영향을 미치거나 성능에 영향을 미칠 수 있습니다.결정적이지 않은 루틴을 DECYSTIC으로 선언하면 Optimizer가 잘못된 실행 계획을 선택하게 되어 예기치 않은 결과를 초래할 수 있습니다.결정론적 루틴을 비결정론적으로 선언하면 사용 가능한 최적화를 사용하지 않게 되어 성능이 저하될 수 있습니다.MySQL 5.0.44 이전에는 DECYSTIC 특성이 인정되지만 옵티마이저에서는 사용되지 않습니다.

저장된 루틴에 다음과 같이 태그를 지정할 수 있습니다.DETERMINISTIC그렇지 않더라도 예상치 못한 결과나 성능 문제가 발생할 수 있습니다.

결정론적 결과는 (평균 시간에 추가된 데이터에 따라) 다른 시간에 반환되는 다른 결과 집합을 참조하지 않습니다.또한 동일한 데이터를 사용하는 여러 시스템의 결과 집합에 대한 참조입니다.예를 들어, uuid() 또는 참조 서버 변수를 포함하는 함수를 실행하는 시스템이 2개 있는 경우, 이들은 NOT DECYSTICAL로 간주되어야 합니다.예를 들어, 함수 호출이 이진 로그(마스터)에 저장된 다음 슬레이브에서 실행되기 때문에 복제에서 유용합니다.자세한 내용과 예는 http://dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html 을 참조하십시오.

따라서 DECYSTICAL의 사용은 (99%의 경우) 올바른 것이며, 오용으로 간주해서는 안 됩니다.

저는 당신의 일과가 결정적이라고 생각합니다.설명서가 명확하지 않아 많은 사람들이 이 문제에 대해 매우 혼란스러워하고 있습니다. 이 문제는 사실 복제에 관한 것입니다.

두 데이터베이스 간에 복제가 설정되어 있는 경우를 고려합니다.마스터 데이터베이스는 입력 파라미터를 포함하여 실행된 모든 저장된 루틴의 로그를 보관하고 이 로그를 슬레이브로 발송합니다.슬레이브는 동일한 입력 파라미터로 동일한 순서로 동일한 저장 루틴을 실행합니다.슬레이브 데이터베이스에 마스터 데이터베이스와 동일한 데이터가 포함됩니까?저장된 루틴이 GUID를 생성하고 데이터베이스에 저장하는 경우, 아니오는 마스터 및 슬레이브 데이터베이스가 달라지며 복제가 중단됩니다.

Deterministic 플래그의 주된 목적은 복제 로그에 이 저장된 루틴에 호출을 포함하는 것이 마스터 데이터베이스와 복제된 슬레이브 간의 차이를 초래하여 안전하지 않은지 여부를 MySQL에 알려주는 것입니다.

Deterministic 플래그가 저장된 루틴에 적합한지 여부를 판단할 때는 다음과 같이 생각해야 합니다.두 개의 동일한 데이터베이스에서 시작하여 입력 매개변수가 동일한 두 데이터베이스 모두에서 루틴을 실행하는 경우에도 데이터베이스가 동일합니까?그들이 그렇다면 저의 일과는 결정적입니다.

루틴이 결정적이지 않다고 선언하면 MySQL은 절차 호출을 복제 로그에만 추가하고 슬레이브에서 절차를 실행해도 동일한 결과가 나타나지 않으므로 기본 데이터베이스의 복제본이 원본과 동일하지 않을 수 있습니다.

루틴이 결정적이지 않은 경우 MySQL은 대신 영향을 받는 행을 복제 로그에 포함해야 합니다.루틴이 결정적이지 않은 상태에서 루틴을 선언하면 아무것도 깨지지 않지만, 절차 호출만으로도 충분했을 때 영향을 받는 모든 행이 복제 로그에 포함되어 성능에 영향을 미칠 수 있습니다.

하나도 빠뜨린 게 없습니다.이 함수는 비결정적입니다.결정적이라고 선언해도 데이터베이스가 녹지는 않지만 성능에 영향을 미칠 수 있습니다.MySQL 사이트: "결정적이지 않은 루틴을 DECYSTIC으로 선언하면 옵티마이저가 잘못된 실행 계획을 선택하게 되어 예상치 못한 결과를 초래할 수 있습니다."그러나 MySQL은 사용자가 선언한 결정론적 루틴이 실제로 결정론적인지 확인하거나 강제하지 않습니다. MySQL은 사용자가 무엇을 하고 있는지 알고 있다고 신뢰합니다.

복제를 설정했거나 언젠가 사용할 수 있는 경우에는 결정론이 중요합니다.예를 들어 행 변경(업데이트 또는 삽입)을 유발하는 비결정적 함수 호출은 이진법(행 기반)을 사용하여 복제해야 하며 결정적 함수는 문 기반으로 복제할 수 있습니다.위의 SQL 예제를 살펴보면 문 기반을 사용하여 복제할 때 동일한 결과가 발생하고 마스터(행 기반)에서 얻은 결과를 사용하여 복제해야 하는 SQL 예제가 흥미롭습니다.문이 적절한 잠금 상태에서 실행되고 슬레이브에서 동일한 순서로 실행되도록 보장될 수 있다면 실제로 결정적입니다.슬레이브가 사용하는 잠금/문 순서(동시성 없음, 문이 시작된 순서대로 연속 처리됨)가 정답이 다를 수 있음을 의미하는 경우 함수는 결정적이지 않아야 합니다.

성능에 큰 영향을 미칠 수 있는 이유에 대한 예를 추가하여 결정론적 함수를 선언하고자 합니다.

SELECT id1, foo(id1) f1
FROM table1
ORDER BY id1
LIMIT 1;

MariaDB 10.6 사용:

foo()가 DECIALTISTIC으로 선언되면 foo()는 단일 반환 행에 대해 한 번만 호출됩니다.

foo()가 Deterministic으로 선언되지 않은 경우, foo()는 단일 행을 반환하기 전에 표 1의 모든 행에 대해 한 번 호출됩니다.오래 걸릴 수도 있어요!!

그래서 저는 "bikeman868"과 "C"를 사용하는 것을 추천합니다.함수가 결정론적인지 여부를 결정하기 위한 Poh" 정의:

결정론적 함수는 데이터베이스의 동일한 상태에서 동일한 입력 매개변수가 주어지면 항상 동일한 결과를 반환합니다.예: POW,SUBstr(),UCASE().

비결정론적 함수는 데이터베이스의 동일한 상태에서 동일한 입력 매개변수가 주어졌을 때 반드시 동일한 결과를 반환하지는 않습니다.예: CURDATE(), RAND(), UUID().

이 외에도 데이터베이스에 저장되거나 외부 용도로만 추출되는 함수의 결과가 어떤 방식으로 사용되는지도 고려할 수 있습니다.

답변을 검토하다가 좀 더 간결하고 업데이트된 답변을 제공하기로 결정했습니다.

결정론적 함수는 데이터베이스의 동일한 상태에서 동일한 입력 매개변수가 주어지면 항상 동일한 결과를 반환합니다.예: POW,SUBstr(),UCASE().

비결정론적 함수는 데이터베이스의 동일한 상태에서 동일한 입력 매개변수가 주어졌을 때 반드시 동일한 결과를 반환하지는 않습니다.예: CURDATE(), RAND(), UUID().

MySQL 8.0 Reference Manual에는 이에 대한 업데이트가 있습니다.

8.2.1.20 함수 호출 최적화

MySQL 함수는 내부적으로 결정론적 또는 비결정론적으로 태그가 지정됩니다.함수의 인수에 대해 고정된 값이 주어지면 다른 호출에 대해 다른 결과를 반환할 수 있는 경우 함수는 비결정적입니다.비결정론적 함수의 예: RAND(), UUID().함수가 비결정적으로 태그 지정된 경우 WHERE 절의 참조는 모든 행(한 테이블에서 선택할 때) 또는 행 조합(다중 테이블 조인에서 선택할 때)에 대해 평가됩니다.MySQL은 또한 인수가 테이블 열인지 상수 값인지 여부와 같은 인수 유형에 따라 함수를 평가할 시기를 결정합니다.테이블 열을 인수로 사용하는 결정론적 함수는 해당 열이 값을 변경할 때마다 평가해야 합니다.비결정적 함수는 쿼리 성능에 영향을 줄 수 있습니다.예를 들어, 일부 최적화를 사용할 수 없거나 더 많은 잠금이 필요할 수 있습니다.다음의 논의는 RAND()를 사용하지만 다른 비결정적 함수에도 적용됩니다.

MySQL 8.0 Reference Manual의 코드 예제입니다.테이블을 만든 다음 id 열 1~49와 같은 49개 행과 "AA", "AB", "AC"와 같은 고유한 문자열을 49개 행까지 데이터에 채울 수 있습니다.실제로는 15개의 행을 수행할 수 있지만 랜덤 함수의 주제인 49개를 15개로 변경해야 합니다.

CREATE TABLE t (id INT NOT NULL PRIMARY KEY, col_a VARCHAR(100));

SELECT * FROM t WHERE id = POW(1,2);
SELECT * FROM t WHERE id = FLOOR(1 + RAND() * 49);

이 코드는 MySQL 8.0 Reference 메뉴얼이 만들려고 하는 포인트를 설명하는 데 도움이 될 것입니다.이것이 도움이 되기를 바랍니다 감사합니다!

언급URL : https://stackoverflow.com/questions/7946553/deterministic-function-in-mysql

반응형