powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Курсоры MySQL: почему ж так медленно?
2 сообщений из 2, страница 1 из 1
Курсоры MySQL: почему ж так медленно?
    #39016817
A-MaR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пример конечно утрированный, но суть отражает.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
--
-- Описание для базы данных test1
--
DROP DATABASE IF EXISTS test_cursor;
CREATE DATABASE IF NOT EXISTS test_cursor
CHARACTER SET cp1251
COLLATE cp1251_general_ci;

-- 
-- Установка базы данных по умолчанию
--
USE test_cursor;

--
-- Описание для таблицы test1
--
CREATE TABLE IF NOT EXISTS test1 (
  IdTest1 int(10) UNSIGNED NOT NULL,
  val boolean,
  PRIMARY KEY (IdTest1)
)
ENGINE = INNODB
AVG_ROW_LENGTH = 37
CHARACTER SET cp1251
COLLATE cp1251_general_ci;

--
-- Описание для таблицы test2
--
CREATE TABLE IF NOT EXISTS test2 (
  IdTest2 int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  IdTest1 int(10) UNSIGNED DEFAULT NULL,
  PRIMARY KEY (IdTest2),
  CONSTRAINT FK_test2_test1_IdTest1 FOREIGN KEY (IdTest1)
  REFERENCES test1 (IdTest1) ON DELETE CASCADE ON UPDATE CASCADE
)
ENGINE = INNODB
AUTO_INCREMENT = 1501
AVG_ROW_LENGTH = 32
CHARACTER SET cp1251
COLLATE cp1251_general_ci;

DELIMITER $$

--
-- Описание для процедуры proc_fill_test1
--
CREATE DEFINER = 'root'@'%'
PROCEDURE proc_fill_test1 ()
BEGIN
  DECLARE i int;
  DELETE
    FROM test1;
  SET i = 1;
  WHILE i < 1000 DO
    INSERT INTO test1 (IdTest1)
      VALUES (i);
    SET i = i + 1;
  END WHILE;
END
$$

--
-- Описание для функции fn_fill_test2
--
CREATE DEFINER = 'root'@'%'
FUNCTION fn_fill_test2 (IN_Id int)
RETURNS boolean
BEGIN
  DECLARE result boolean;
  DECLARE tmp decimal(5,1);
  DELETE
    FROM test2
  WHERE IdTest1 = IN_Id;
  SET tmp = IN_Id/2;
  SET result = (tmp = ROUND(IN_Id/2));
  IF result THEN
    INSERT INTO test2 (IdTest1)
      VALUES (IN_Id);
  END IF;
  RETURN result;
END
$$

--
-- Описание для процедуры proc_fill_test2_with_cursor
--
CREATE DEFINER = 'root'@'%'
PROCEDURE proc_fill_test2_with_cursor ()
BEGIN
  DECLARE vId int;
  DECLARE Done tinyint(1) DEFAULT 0;
  DECLARE cur CURSOR FOR
  SELECT
    t.IdTest1
  FROM test1 t
  WHERE IdTest1 > 0;
  DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET Done = 1;
  SET Done = FALSE;
  OPEN cur;
  REPEAT
    FETCH cur INTO vid;
    SET @result = fn_fill_test2(vId);
  UNTIL Done
  END REPEAT;
  CLOSE cur;
END
$$

--
-- Описание для процедуры proc_fill_test2_without_cursor
--
CREATE DEFINER = 'root'@'%'
PROCEDURE proc_fill_test2_without_cursor ()
BEGIN
  UPDATE test1 t
  SET Val = fn_fill_test2(t.IdTest1);
END
$$

DELIMITER ;

CALL proc_fill_test1;
DROP PROCEDURE proc_fill_test1;


Требуется пробежаться по записям таблицы test1 и, в соответствии с определенной логикой, добавить записи в подчиненную таблицу test2.
Процедура proc_fill_test2_with_cursor делает это с использованием курсора, proc_fill_test2_without_cursor - без него, но с использованием лишнего поля в test1. Обе процедуры используют одну и ту же функцию fn_fill_test2. Вторая процедура отрабатывает в несколько раз быстрее. Может я как-то неправильно создаю или использую курсор? Если же курсоры - это действительно тормоз, то можно ли обойтись без них, но и без лишних полей? Триггеры не подходят, т.к. в момент вставки в test2 никакой модификации данных в test1 не предусмотрено.
...
Рейтинг: 0 / 0
Курсоры MySQL: почему ж так медленно?
    #39016836
A-MaR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пардон, все оказалось проще: select fn_fill_test2(t.IdTest1) FROM test1 t решает проблему
...
Рейтинг: 0 / 0
2 сообщений из 2, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Курсоры MySQL: почему ж так медленно?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]