私はこの問題のアプローチに感謝します、私はmysqlに宝くじシステムを持っています、このシステムは毎秒多くのトランザクションを受け取ります。ベットを許可する前に、各番号の合計金額を確認する必要があります。この目的のために、次のように考えています。
CREATE ALGORITHM=MERGE DEFINER=user@% SQL SECURITY DEFINER
VIEW view_todays_bet AS select number, sum(bet_amout) as total_bet from salestable;
このビューでは、たとえば次のような結果になります。
Number total_bet
===== ========
01 1500
05 2000
...
99 20
新しいベットがあるときは、ビューから選択を行い、それが問題が発生した瞬間です。たとえば、05番の残高を知りたい場合は、この選択を行います。
select total_bet from view_todays_bet where number = '05';
メインテーブルから直接選択を行うとsalestable
他のベットからの挿入がたくさんあるためブロックされますが、ビューからの選択が遅すぎます。この問題についてのアプローチを教えてください。
ありがとう。
これがテーブルの場合の実際の構造です。ヘッダー/詳細テーブルと、両方の結合から作成されたビュー。
CREATE TABLE `sales_details` (
`codpais` varchar(2) NOT NULL DEFAULT '',
`numero` varchar(7) NOT NULL DEFAULT '',
`verificador` varchar(10) NOT NULL DEFAULT '',
`codterminal` varchar(8) NOT NULL DEFAULT '',
`item` int(4) NOT NULL DEFAULT '1',
`codloteria` varchar(3) NOT NULL DEFAULT '',
`secuencia` varchar(2) NOT NULL DEFAULT '' COMMENT 'Aqui van los numeros jugados',
`codjuego` varchar(3) NOT NULL DEFAULT '',
`numeros` varchar(30) NOT NULL DEFAULT '' COMMENT 'Aqui van los numeros jugados',
`monto` double NOT NULL DEFAULT '0',
`numsorteos` int(11) NOT NULL DEFAULT '1',
`horasorteo` varchar(5) NOT NULL DEFAULT '00:00',
`codloteria2` varchar(3) NOT NULL DEFAULT '',
`secuencia2` varchar(2) NOT NULL DEFAULT '',
`nombrecorto2` varchar(30) NOT NULL DEFAULT '',
`horasorteo2` varchar(5) NOT NULL DEFAULT '',
`numerosganadores` varchar(10) NOT NULL DEFAULT '',
`montopremio` double NOT NULL DEFAULT '0',
`ganaprimero` double NOT NULL DEFAULT '0',
`ganasegundo` double NOT NULL DEFAULT '0',
`ganatercero` double NOT NULL DEFAULT '0',
`ganacuarto` double NOT NULL DEFAULT '0',
`porciento` double NOT NULL DEFAULT '0',
PRIMARY KEY (`codpais`,`numero`,`verificador`,`codterminal`,`item`),
KEY `codloteria` (`codloteria`),
KEY `codjuego` (`codjuego`),
KEY `codloteria2` (`codloteria2`)
) ENGINE=InnoDB;
CREATE TABLE `sales_header` (
`codpais` varchar(2) NOT NULL DEFAULT '',
`numero` varchar(7) NOT NULL DEFAULT '',
`verificador` varchar(10) NOT NULL DEFAULT '',
`codterminal` varchar(8) NOT NULL DEFAULT '',
`stan` varchar(6) NOT NULL DEFAULT '',
`tx` varchar(2) NOT NULL DEFAULT '',
`cajero` varchar(15) NOT NULL DEFAULT '',
`codempresa` varchar(2) NOT NULL DEFAULT '',
`codbase` varchar(3) NOT NULL DEFAULT '',
`codbanca` varchar(7) NOT NULL DEFAULT '',
`codgrupo` varchar(2) NOT NULL DEFAULT '',
`codprovincia` varchar(3) NOT NULL DEFAULT '',
`codciudad` varchar(2) NOT NULL DEFAULT '',
`codmunicipio` varchar(4) NOT NULL DEFAULT '',
`codlocal` varchar(3) NOT NULL DEFAULT '',
`total` double NOT NULL DEFAULT '0',
`fechasorteo` date NOT NULL DEFAULT '0001-01-01',
`fechasistema` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`fechapos` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`fechacancelacion` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`numerocancela` varchar(10) NOT NULL DEFAULT '',
`terminalcancela` varchar(8) NOT NULL DEFAULT '',
`turno` int(9) unsigned NOT NULL DEFAULT '0',
`tasa` double NOT NULL DEFAULT '0',
`esganador` varchar(1) NOT NULL DEFAULT 'N',
`fuecobrado` varchar(1) NOT NULL DEFAULT 'N',
`sorteocerrado` varchar(1) NOT NULL DEFAULT 'N',
`fechacobrado` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`terminalcobrado` varchar(8) NOT NULL DEFAULT '',
`usuariocobrado` varchar(15) NOT NULL DEFAULT '',
`verificadorcobrado` varchar(20) NOT NULL DEFAULT '',
`totalcobrado` double NOT NULL DEFAULT '0',
`estatus` varchar(1) NOT NULL DEFAULT 'A' COMMENT 'A- Activo, R-Reversado, N-Anulada',
`numrecarga` varchar(30) NOT NULL DEFAULT '',
`autoincrecarga` varchar(4) NOT NULL DEFAULT '',
`sincronizada` varchar(1) NOT NULL DEFAULT 'N',
`reimpreso` varchar(1) NOT NULL DEFAULT 'N',
`porciento` double NOT NULL DEFAULT '0',
`bk` varchar(1) NOT NULL DEFAULT 'N',
`codcliente` varchar(5) NOT NULL DEFAULT '',
`calcporciento` varchar(1) NOT NULL DEFAULT 'T',
PRIMARY KEY (`codpais`,`numero`,`verificador`,`codterminal`),
KEY `stan` (`stan`),
KEY `tx` (`tx`),
KEY `fechasorteo` (`fechasorteo`),
KEY `fechasistema` (`fechasistema`),
KEY `estatus` (`estatus`),
KEY `codconsorcio` (`codbase`),
KEY `codempresa` (`codempresa`),
KEY `codbanca` (`codbanca`),
KEY `codgrupo` (`codgrupo`),
KEY `bk` (`bk`),
KEY `codcliente` (`codcliente`),
KEY `esganador` (`esganador`),
KEY `numrecarga` (`numrecarga`)
) ENGINE=InnoDB;
CREATE ALGORITHM=UNDEFINED DEFINER=`user`@`%` SQL SECURITY DEFINER VIEW `view_todays_bet` AS select `vd`.`codpais` AS `codpais`,`vd`.`codloteria` AS `codloteria`,`vd`.`codjuego` AS `codjuego`,sum(`vd`.`monto`) AS `monto`,`fnNumeroCRC`(`vd`.`numeros`) AS `crc` from (`sales_details` `vd` join `sales_header` `vh`) where ((`vd`.`codpais` = `vh`.`codpais`) and (`vd`.`numero` = `vh`.`numero`) and (`vd`.`verificador` = `vh`.`verificador`) and (`vd`.`codterminal` = `vh`.`codterminal`) and (`vh`.`fechasorteo` = date_format(sysdate(),'%Y-%m-%d')) and (`vh`.`estatus` = 'A'))
group by 1,2,3,5
order by 1,2,3,5
ここでいくつかのことが起こっています:
_CREATE VIEW
_ステートメントにSUM()
関数が含まれています。あなたのALGORITHM
はMERGE
として指定されていますが、ドキュメントで説明されているように、実際にはTEMPTABLE
になります here :
MERGEアルゴリズムを使用できない場合は、代わりに一時テーブルを使用する必要があります。ビューに次の構成要素のいずれかが含まれている場合、MERGEは使用できません。集計関数(SUM()、MIN()、MAX()、COUNT()など)
したがって、一時テーブルを使用しています。 TEMPTABLEアルゴリズムのこの利点により、「ブロック」が表示されないのではないかと思います。
TEMPTABLEを明示的に選択する理由は、一時テーブルが作成された後、ステートメントの処理を完了するために使用される前に、基礎となるテーブルのロックを解放できるためです。これにより、MERGEアルゴリズムよりも迅速にロックが解放されるため、ビューを使用する他のクライアントがブロックされないようにします。
ただし、TEMPTABLE
アルゴリズムの問題は、インデックスがない/使用しないことです [src] :
ビュー処理は最適化されていません:
ビューにインデックスを作成することはできません。
インデックスは、マージアルゴリズムを使用して処理されたビューに使用できます。ただし、temptableアルゴリズムで処理されるビューは、基になるテーブルのインデックスを利用できません(ただし、一時テーブルの生成中にインデックスを使用できます)。
したがって、直接クエリがブロックされる理由について、テーブルの基本的な構造を知る必要があります。
number
、_bet_amount
_)にインデックスがない場合は、作成することを検討してください。上記のポイントが既に実行されていて、何らかの理由でsalestable
テーブルに対するクエリを直接ブロックしている場合、一時テーブルを変更するトリガーを作成して、貧しい人々のマテリアライズドビューを設定できます。各番号と現在の合計。
遅いビュー
代替ソリューションで解決
機能的な代替案は、パラメーターを渡して、ビュークエリをプロシージャにカプセル化することです。これは、複数のテーブル間で複数の結合クエリを使用してVIEWSが遅くなるという問題を改善する簡単なソリューションです。
DELIMITER ;;
CREATE PROCEDURE `SP_QUERY_VIEW_WITH_PARAMETERS`(IN p_having VARCHAR(300))
COMMENT 'Executes the statement'
BEGIN
SET @v_having = p_having;
SET @v_sql=CONCAT('SELECT
id AS id_emp ,
user AS emp_name,
.
.
.
FROM table1
UNION ALL
SELECT
idtifier_us AS id_emp ,
description AS emp_name,
.
.
.
FROM table2');
SET @v_sql2 = CONCAT(@v_sql,@v_having);
PREPARE stmt FROM @v_sql2;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END ;;
DELIMITER ;
CALL `SP_QUERY_VIEW_WITH_PARAMETERS`('having id_emp=63 and emp_name like ''VANDERLEI%'' and created_at between ''2019-05-01'' and ''2019-05-17'' ');
この代替案は、クエリの実行時にインデックスによる最適化を保持します
注:「どこ」でも使用できますが、より単純なクエリを使用します