Моят личен и професионален живот
2019-12-25
2019-12-05
Режим картина-в-картината в Firefox 71
Публикувано от
Georgi D. Sotirov
в
18:22
0
коментар(и)
2019-10-18
Нови възможности в MySQL 8.0.18
Оптимизация с хеш съединение
- Nested-Loop Join - най-простия където всеки ред от външния цикъл се подава към вътрешния цикъл за обработка. Очевидния недостатък на този е, че вътрешната таблица трябва да бъде четена много пъти.
- Block Nested Loop (BNL) - използва буфериране на редове от външната таблица, за да намали броя на пъти в които вътрешната таблица се чете. В този случай, вместо да се подава само един ред към вътрешния цикъл множество редове от буфера могат да бъдат подадени наведнъж. Това значително намалява броя пъти в които вътрешната таблица трябва да бъде четена. Разбира се това изисква повече памет (виж join_buffer_size). Този алгоритъм се използва за range, index или ALL типове съединения.
SELECT E.ename, E.sal, JS.sal_min, JS.sal_max
FROM emp E,
job_sal JS
WHERE E.job = JS.job
AND E.sal NOT BETWEEN JS.sal_min AND JS.sal_max;
+----------------------------------------------------------------------------------------+
| EXPLAIN |
+----------------------------------------------------------------------------------------+
| -> Filter: (E.sal not between JS.sal_min and JS.sal_max) (cost=499211.71 rows=442901)
-> Inner hash join (E.job = JS.job) (cost=499211.71 rows=442901)
-> Table scan on E (cost=1962.39 rows=996514)
-> Hash
-> Table scan on JS (cost=0.75 rows=5)
|
+----------------------------------------------------------------------------------------+
1 row in set (0.0023 sec)
EXPLAIN ANALYZE
- времето за връщане на първия ред (в мс);
- времето за връщане на всички редове (в мс);
- броя на прочетените редове;
- броя цикли.
+-------------------------------------------------------------------------------------------------------+
| EXPLAIN |
+-------------------------------------------------------------------------------------------------------+
| -> Filter: (E.sal not between JS.sal_min and JS.sal_max)
(cost=502072.82 rows=442901) (actual time=0.372..747.742 rows=915768 loops=1)
-> Inner hash join (E.job = JS.job)
(cost=502072.82 rows=442901) (actual time=0.355..575.011 rows=1000014 loops=1)
-> Table scan on E (cost=2534.62 rows=996514) (actual time=0.185..353.877 rows=1000014 loops=1)
-> Hash
-> Table scan on JS (cost=0.75 rows=5) (actual time=0.133..0.144 rows=5 loops=1)
|
+-------------------------------------------------------------------------------------------------------+
1 row in set (0.7754 sec)
MySQL е само OpenSSL
С тази версия поддръжката на yaSSL и WolfSSL библиотеките са премахва, така че MySQL може да се компилира само с OpenSSL. Аз лично винаги съм изграждал MySQL с OpenSSL (т.е. използвайки ключа -DWITH_SSL=system), защото това е което идва с Slackware, но разбира се по-важното е, че "комбинацията MySQL/OpenSSL е много добре изпробвана и доказана в продукция" както Georgi Kodinov обяснява в публикацията си MySQL is OpenSSL-only now !.Пространствен
Point
и Point
, или Point
и MultiPoint
както преди.
Публикувано от
Georgi D. Sotirov
в
13:00
0
коментар(и)
Етикети: MySQL
2019-09-29
Нови използвания на TREE план за изпълнение в MySQL 8.0.18
- HASH съединения ще бъдат видими само в TREE формат. Намирам това за странно, защото бихте очаквали да видите тази операция без значение от формата на плана, така че се надявам да бъде разширено в бъдеще.
- EXPLAIN ANALYZE всъщност ще изпълнява заявката и ще дава информация за времето на изпълнение. Ще включва също и допълнителна информация на база итератор относно това как оценката на оптимизатора се сравнява с действителното изпълнение.
Публикувано от
Georgi D. Sotirov
в
17:22
0
коментар(и)
Етикети: MySQL
2019-07-31
Нови възможности в MySQL 8.0.17
Индекси върху множество стойности
CREATE TABLE translators (
id INT AUTO_INCREMENT,
jdata JSON,
PRIMARY KEY(id)
);
- Случай 1 - масив от низове
INSERT INTO translators (jdata)
VALUES ('{"name": "T1", "langs": ["English", "French", "Spanish"]}'),
('{"name": "T2", "langs": ["English", "Spanish"]}'),
('{"name": "T3", "langs": ["French", "Spanish"]}');
SELECT id, jdata->>'$.name', jdata->'$.langs'
FROM translators
WHERE 'English' MEMBER OF (jdata->'$.langs');
SELECT id, jdata->>'$.name', jdata->'$.langs'
FROM translators
WHERE JSON_OVERLAPS(jdata->'$.langs', '["English"]');
+----+------------------+----------------------------------+
| id | jdata->>'$.name' | jdata->'$.langs' |
+----+------------------+----------------------------------+
| 1 | T1 | ["English", "French", "Spanish"] |
| 2 | T2 | ["English", "Spanish"] |
+----+------------------+----------------------------------+
2 rows in set (0.00 sec)
ALTER TABLE translators
ADD INDEX idx_langs_arr ((CAST(jdata->'$.langs' AS CHAR(8) ARRAY)));
- Случай 2 - масив от обекти
INSERT INTO translators (jdata)
VALUES ('{"name": "T1", "langs": [{"lang": "English"}, {"lang": "French"}, {"lang": "Spanish"}]}'),
('{"name": "T2", "langs": [{"lang": "English"}, {"lang": "Spanish"}]}'),
('{"name": "T3", "langs": [{"lang": "French"}, {"lang": "Spanish"}]}');
SELECT id, jdata->>'$.name', jdata->'$.langs[*].lang'
FROM translators
WHERE 'English' MEMBER OF (jdata->'$.langs[*].lang');
SELECT id, jdata->>'$.name', jdata->'$.langs[*].lang'
FROM translators
WHERE JSON_OVERLAPS(jdata->'$.langs[*].lang', '["English"]');
ALTER TABLE translators
ADD INDEX idx_langs_obj ((CAST(jdata->'$.langs[*].lang' AS CHAR(8) ARRAY)));
JSON
- Функцията JSON_OVERLAPS сравнява два JSON документа и връща истина "ако двата документа имат някоя обща ключ-стойност двойка или елементи на масив". Както MEMBER OF и JSON_CONTAINS функцията JSON_OVERLAPS може да се облагодетелства от индекси върху множество стойности.
- Функциите JSON_SCHEMA_VALID и JSON_SCHEMA_VALIDATION_REPORT са добавени във връзка с поддръжката на JSON Schema. Първата проверява JSON документ спрямо JSON схема и връща истина ако е верен иначе лъжа, така че да може да се ползва като CHECK ограничение. Втората ще предостави подробности по грешките от проверката под формата на JSON документ.
Преобразуване към FLOAT, DOUBLE и REAL
SELECT CAST('1.23.34' AS FLOAT) cast_res, CONVERT('1.23.34', FLOAT) conv_res;
+--------------------+--------------------+
| cast_res | conv_res |
+--------------------+--------------------+
| 1.2300000190734863 | 1.2300000190734863 |
+--------------------+--------------------+
1 row in set, 2 warnings (0.00 sec)
+---------+------+---------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '1.23.34' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '1.23.34' |
+---------+------+---------------------------------------------+
2 rows in set (0.00 sec)
SELECT CAST('1.23.34' AS DOUBLE) cast_res, CONVERT('1.23.34', DOUBLE) conv_res;
SELECT CAST('1.23.34' AS REAL) cast_res, CONVERT('1.23.34', REAL) conv_res;
+----------+----------+
| cast_res | conv_res |
+----------+----------+
| 1.23 | 1.23 |
+----------+----------+
1 row in set, 2 warnings (0.00 sec)
CLONE команда
- MySQL InnoDB Cluster from scratch – even more easy since 8.0.17 от Frédéric Deschamps;
- Clone: Create MySQL instance replica от Debarun Banejee; и
- Create an Asynchronous MySQL Replica in 5 minutes отново от Frédéric Deschamps.
Обезценяавния
- Функцията FOUND_ROWS и модификатора на заявки SQL_CALC_FOUND_ROWS. Документацията предлага използването на COUNT(*) за да се намери броя редове.
- Атрибути на числови типове данни:
- Дължина за показване на целочислени типове данни. Вече се показва предупрежение "1681 Integer display width is deprecated and will be removed in a future release." ако се опитате да създадете таблици с INT(11) например. Аз имам доста такива определения както са били предоставени от mysqldump и MySQL Workbench, така че ще трябва да ги махна всички преди изразите да бъдат отхвърлени с грешка в бъдеще.
- Атрибута ZEROFILL. Така или иначе никога не съм го ползвал.
- Атрибута UNSIGNED за FLOAT, DOUBLE, и DECIMAL типове данни. Също не съм го ползвал никога.
- AUTO_INCREMENT поддръжката за FLOAT и DOUBLE типове данни. Някой?
- Синтаксиса FLOAT(M,D) и DOUBLE(M,D) за указването на броя цифри за типове с плаваща запетая.
- Логически оператори && (двоен амперсанд), който е синоним на AND, || (двоен пайп), който е синоним на OR и ! (удивителна), която е синоним на NOT. Не съм сигурен, че някога съм ги ползвал дори в ежедневни заявки, защото намирам ползването на AND, OR и NOT за доста по-изразително.
- Ключовата дума BINARY за указване на _bin колации. Никога не съм я ползвал също така.
Оправени бъгове
SET binlog_format = 'STATEMENT';
SET binlog_row_image = 'minimal';
UPDATE tst SET end_date = '2019-04-20' WHERE id = 1;
/* Error Code: 3819. Check constraint 'chk_dat' is violated. */
Публикувано от
Georgi D. Sotirov
в
20:26
0
коментар(и)
Етикети: Разработка, MySQL
2019-06-05
Формат на план за изпълнение TREE в MySQL 8.0.16
- TRADITIONAL - стария табличен план за изпълнение подходящ за конзола;
- JSON - план за изпълнение в JSON използван от MySQL Workbench за показване на хубави графики в Visual Explain, които използвам в презентации.
Query 1: С използване на LEFT OUTER JOIN и производна таблица
SELECT D.dname, DT.min_sal, DT.avg_sal, DT.max_salFROM dept D
LEFT OUTER JOIN
(SELECT E.deptno,
MIN(E.sal) min_sal, AVG(E.sal) avg_sal, MAX(E.sal) max_sal
FROM emp E
GROUP BY E.deptno
) AS DT
ON DT.deptno = D.deptno;
Query 2: С използване на LATERAL производна таблица
SELECT D.dname, LDT.min_sal, LDT.avg_sal, LDT.max_salFROM dept D,
LATERAL
(SELECT MIN(E.sal) min_sal, AVG(E.sal) avg_sal, MAX(E.sal) max_sal
FROM emp E
WHERE E.deptno = D.deptno
) AS LDT;
Query 1
+----+-------------+------------++-------++-------------+---------+-------------------+------++-------+| id | select_type | table || type || key | key_len | ref | rows || Extra |
+----+-------------+------------++-------++-------------+---------+-------------------+------++-------+
| 1 | PRIMARY | D || ALL || NULL | NULL | NULL | 4 || NULL |
| 1 | PRIMARY | <derived2> || ref || <auto_key0> | 5 | dept_emp.D.deptno | 2 || NULL |
| 2 | DERIVED | E || index || fk_deptno | 5 | NULL | 14 || NULL |
+----+-------------+------------++-------++-------------+---------+-------------------+------++-------+
3 rows in set, 1 warning (0.01 sec)
+-------+------+-----------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-----------------------------------------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select `dept_emp`.`D`.`dname` AS `dname`... left join (
/* select#2 */ select `dept_emp`.`E`.`deptno` AS `deptno`,min(`dept_emp`.`E`.`sal`) AS `min_sal`... |
+-------+------+-----------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
Query 2
+----+-------------------+------------++------++-----------+---------+-------------------+------++----------------------------+| id | select_type | table || type || key | key_len | ref | rows || Extra |
+----+-------------------+------------++------++-----------+---------+-------------------+------++----------------------------+
| 1 | PRIMARY | D || ALL || NULL | NULL | NULL | 4 || Rematerialize (<derived2>) |
| 1 | PRIMARY | <derived2> || ALL || NULL | NULL | NULL | 2 || NULL |
| 2 | DEPENDENT DERIVED | E || ref || fk_deptno | 5 | dept_emp.D.deptno | 1 || NULL |
+----+-------------------+------------++------++-----------+---------+-------------------+------++----------------------------+
3 rows in set, 2 warnings (0.0006 sec)
+-------+------+-----------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-----------------------------------------------------------------------------------------------------+
| Note | 1276 | Field or reference 'dept_emp.D.deptno' of SELECT #2 was resolved in SELECT #1 |
| Note | 1003 | /* select#1 */ select `dept_emp`.`D`.`dname` AS `dname`, ... join lateral (
/* select#2 */ select min(`dept_emp`.`E`.`sal`) AS `min_sal`... |
+-------+------+-----------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
Query 1
+-----------------------------------------------------------------+| EXPLAIN |
+-----------------------------------------------------------------+
| -> Nested loop left join
-> Table scan on D
-> Index lookup on DT using <auto_key0> (deptno=d.deptno)
-> Materialize
-> Group aggregate: min(e.sal), avg(e.sal), max(e.sal)
-> Index scan on E using fk_deptno |
+-----------------------------------------------------------------+
1 row in set (0.0025 sec)
Query 2
+----------------------------------------------------------------------+| EXPLAIN |
+----------------------------------------------------------------------+
| -> Nested loop inner join
-> Invalidate materialized tables (row from D)
-> Table scan on D
-> Table scan on LDT
-> Materialize (invalidate on row from D)
-> Aggregate: min(e.sal), avg(e.sal), max(e.sal)
-> Index lookup on E using fk_deptno (deptno=d.deptno) |
+----------------------------------------------------------------------+
1 row in set, 1 warning (0.0007 sec)
Note (code 1276): Field or reference 'dept_emp.D.deptno' of SELECT #2 was resolved in SELECT #1
Публикувано от
Georgi D. Sotirov
в
19:38
0
коментар(и)
Етикети: MySQL
2019-05-24
Преводи на Bugzilla 5.0.5 и 5.0.6
За превода
Надграждане
Тази сутрин, след като подготвих преводите, успях да надградя инсталацията ми, което беше абсолютно безпроблемно следвайки инструкциите за директно надграждане от Git. С 5.0.5 таблицата bugs_fulltext беше преобразувана от MyISAM в InnoDB, а с 5.0.6 типа на полетата type_id в таблиците flaginclusions, flagexclusions и flags беше сменен от smallint на mediumint (виж Integer types), което трябва да позволи много повече флагове. Забавих се малко само защото трябваше да поизчистя някои локални промени и скрия (с .gitignore) някои файлове (журнали, кръпки, архиви с преводи, и др.). Това ме подсети и да пусна pull request за една от локалните ми промени - добавяне на viewport meta таг, което е важно в днешно време за поддръжката на мобилни устройства.Изтегляне на преводите
Приятно ползване! И разбира се честит Ден на българската просвета и култура и на славянската писменост!
Публикувано от
Georgi D. Sotirov
в
13:04
0
коментар(и)
Етикети: Преводи, Bugzilla BG
2019-04-30
Нови възможности в MySQL 8.0.16 екосистемата
Start pushing for Semantic Versioning to be adopted at MySQL, and you will avoid this kind of miscommunications— Giuseppe Maxia (@datacharmer) February 1-st 2019
MySQL Server
E, какво е новото в новата версия на сървъра. Ето това което забелязах.CHECK ограничения
ON UPDATE
, ON DELETE
).Ето първия ми пример. Мисля, че доста често има по две дати в таблица (напр. начална и крайна дата), които трябва да представляват началото и края на нещо, така че трябва да се в хронологичен ред. Нека да го направим с таблицата emp от примерната DEPT и EMP схема на Оракъл, която съм пригодил за MySQL.
ADD COLUMN retdate DATE AFTER hiredate,
ADD CONSTRAINT ret_after_hire CHECK (retdate > hiredate);
UPDATE emp
SET retdate = STR_TO_DATE('1019-04-25', '%Y-%m-%d')
WHERE empno = 7369;
1 row(s) affected Rows matched: 1 Changed: 1 Warnings: 0
ADD CONSTRAINT emp_chks CHECK (hiredate >= CURDATE() AND sal > 0);
ADD COLUMN created DATE DEFAULT (hiredate);
MODIFY COLUMN created DATE NOT NULL DEFAULT (CURDATE()),
ADD CONSTRAINT emp_chks CHECK (hiredate >= created AND sal > 0);
INSERT INTO emp
(empno, ename, job, mgr, hiredate, sal)
VALUES
(9999, 'MULDER', 'INVESTIG.', 7839, '2019-04-25', 4242);
Пространствени данни
Сървъра прави цялостно надграждане
--validate-config
за проверка на конфигурацията на сървъра както администраторите са свикнали с други сървъри (напр. Apache). Това е наистина важно особено за среди в продукция, където неочаквания престой може да е крайно неприятен. Прочетете повече в Server Configuration Validation.Системни потребители
MySQL сметки вече се категоризират и така разграничават като системни (които притежават SYSTEM_USER привилегия) и обикновени потребители (които не притежават). Това допринася за по-добро разделение на ролите, тъй като само системни потребители могат да извършват определени административни операции върху системни сметки. Преди това всеки потребител с подходящите привилегии можеше например да изтрие всяка сметка или убие всяка връзка принадлежаща на всеки потребител. Възможно е също така да се отнемат глобални привилегии частично за определени схеми (т.е. като изключения) чрез новата системна променлива partial_revokes, което преди това извикваше задаването на права поотделно за всички съществуващи схеми и добавяне на пава за всяка нова схема.Сигурност
MySQL Router
MySQL Shell
MySQL Workbench
Публикувано от
Georgi D. Sotirov
в
13:54
0
коментар(и)
Етикети: Разработка, MySQL
2019-03-30
Приключвам с пощата на Dir.bg
- копиране на около 1 ГБ писма, което не би трябвало да е проблем като се има в предвид капацитета на днешните връзки стига разбира се услугата да се появи отново на което силно се надявам, защото имам някои важни писма.
- пренасочване на N на брой услуги към пощенския ми адрес в Gmail. Това ще е трудна задача, защото дори не съм сигурен, че ще мога да се сетя за всички въпреки, че пазя писмата за регистрация, но затова за сега смятам да задържа и адреса в Dir.bg докато не прехвърля всичко. Вече започнах, защото не получавах писмата от БГПО.
- обновяване на страници в Интернет, изходен код и други.
Това е. Може би ще пусна нещо кратко, когато приключа с миграцията.
Публикувано от
Georgi D. Sotirov
в
12:23
0
коментар(и)
Етикети: Проблеми