Arxiv

Posts Tagged ‘prepared statement’

Prepared Statement in MySQL

Mart 13, 2012 2 şərh

İlk öncə onu deyim ki, biz bu yazıda “city” table-ından istifadə edəcik. Link To Download City.sql. Sadəcə city.sql faylını run edin.
Yazının sonunda isə kiçik performance müqayisəsi var ki, ora da diqqət etsəniz əla olar 🙂
Prepared Statement SQL syntax-ı 3 SQL statement üzərində qurulub:
1. PREPARE — yaradır
2. EXECUTE — işlədir
3. DEALLOCATE PREPARE — silir
Misallarla izah edək. Aşağıdakı prepared statement-lər 2-si də tamamilə eynidir. Sadəcə yazılış fərqləri var.

mysql> PREPARE stmt1 FROM 'SELECT name, population FROM city WHERE countrycode=?';
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> SET @a='AFG';
Query OK, 0 rows affected (0.00 sec)

mysql> EXECUTE stmt1 USING @a;
+----------------+------------+
| name           | population |
+----------------+------------+
| Kabul          |    1780000 |
| Qandahar       |     237500 |
| Herat          |     186800 |
| Mazar-e-Sharif |     127800 |
+----------------+------------+
4 rows in set (0.00 sec)

İkinci növ yazılış tərzi isə:

mysql> SET @s='SELECT name, population FROM city WHERE countrycode=?';
Query OK, 0 rows affected (0.00 sec)

mysql> PREPARE stmt2 FROM @s;
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> SET @b='AFG';
Query OK, 0 rows affected (0.00 sec)

mysql> EXECUTE stmt2 USING @b;
+----------------+------------+
| name           | population |
+----------------+------------+
| Kabul          |    1780000 |
| Qandahar       |     237500 |
| Herat          |     186800 |
| Mazar-e-Sharif |     127800 |
+----------------+------------+
4 rows in set (0.00 sec)

Prepared Statement-in yaradılmasına və istifadəsinə baxdıqdan sonra indi isə onun haqda bəzi maraqlı məlumatlar verək. Prepared Statement connection(session) spesifikdir. Yəni hər hansı bir user Prepared Statement yaradır və daha sonra disconnect olursa, həmin Prepared Statement avtomatik olaraq silinir. Gələn dəfə connect olanda yenisini yaratmaq məcburiyyətində qalacaq.
MySQL-də eyni zamanda (simultaneously) neçə Prepared Statement yaratmaq olar? Buna max_prepared_stmt_count system dəyişəni nəzarət edir.

mysql> select @@max_prepared_stmt_count;
+---------------------------+
| @@max_prepared_stmt_count |
+---------------------------+
|                     16382 |
+---------------------------+
1 row in set (0.00 sec)

Cavab 16382. Bu system dəyişənindən istifadə edərək biz həm də Prepared Statement-in istifadəsinin qarşısını ala bilərik. Bunun üçün sadəcə max_prepared_stmt_count=0 edək.

mysql> set global max_prepared_stmt_count=0;
Query OK, 0 rows affected (0.00 sec)

Və daha sonra Prepared Statement yaratmağa calışaq:

Mövcud olmayan Prepared Statement-dən istifadə etməyə çalışmaq ERROR-la nəticələnir:

Onu da qeyd edək ki, artıq mövcud olan eyni adlı Prepared Statement yaratmaq istərkən, əvvəlcə köhnəsi silinir daha sonra yerinə yenisi yaradılır. Məhz buna görədir ki, əgər yenisini yaradarkən hər hansı bir ERROR baş verirsə, köhnə Prepared Statement silinir lakin yerinə yenisi yaradılmır 🙂 Dəhşətdir elə deyil mi? 😛

mysql> SET @c='NLD';
Query OK, 0 rows affected (0.00 sec)

mysql> PREPARE stmt1 FROM 'SELECT ame, population FROM city WHERE countrycode=?';
ERROR 1054 (42S22): Unknown column 'ame' in 'field list'
mysql> EXECUTE stmt1 USING @c;
ERROR 1243 (HY000): Unknown prepared statement handler (stmt1) given to EXECUTE

Gördüyümüz kimi name yerinə ame yazılıb məhz bu səhv stmt1-in tamamilə silinməsinə gətirib çıxarıb. Gəlib çatdıq mənim fikrimcə ən maraqlı yerə. ƏSAS MƏSƏLƏ=PERFORMANCE 🙂

İlk öncə city-yə bənzər(eyni) vir table yaradaq:

CREATE TABLE city_log AS SELECT * FROM world.city;

Daha sonra isə Prepared Statement-imizi yaradaq:

PREPARE stmt FROM 'select * from city_log where population > ?';
SET @var=1;

Və işlədək:

EXECUTE stmt USING @var;

Query Profile-a baxaq:

Göstərici — 0.019668
İndi isə eyni şeyi adi select ilə edək:

SELECT * FROM city_log WHERE population>1;

Göstərici — 0.019888
Elə də böyük fərq hiss olunmadı amma ancaq lakin davam edək 🙂
Prepared Statement-i başqa cür işlədək:

SET @ var2=0;
EXECUTE stmt USING @var2;

Göstərici — 0.004675
Eyni şeyi select-lə etsək:

select * from city_log where population>0;

Göstərici — 0.019516
İndi isə biraz ümumiləşdirib yazaq.
Prepared Statement 1ci istifadəsi : 0.019668, 2ci istifadəsi : 0.004675
Select 1ci istifadəsi : 0.019888, 2ci istifadəsi : 0.019516
Fərq göz önündədir məncə 🙂

Kateqoriyalar: MySQL Etiketlər: ,