Pour moi qui bosse dans le monde de la traduction, je ne peux que confirmer ça. Encore récemment j'ai dû accepter de faire des coupures sur des espaces insécables (donc en contradiction totale avec la définition de ce caractère) juste parce que les traducteurs les aiment tellement qu'ils t'en foutent vraiment n'importe où. Et le copier-coller, encore d'accord, c'est presque la règle.
Quant aux fautes d'orthographe, ils veulent justement pouvoir les trouver, ne serait-ce que pour les corriger...
Eh bien voila, enfin un qui comprend la question! Bon je vais étudier ça en détail, si je vois des choses importantes à signaler j'en reparlerai plus tard.
[EDIT]
Bon après avoir regardé, je dirais que bah, c'est un début mais c'est incomplet. On voit très bien par exemple la différence entre le français qui considère que É est équivalent à E, et le polonais qui voit Ą comme une lettre distincte entre A et B. Par contre quand on voit en français que Œ est entre O et P, on se demande si les collations la voient vraiment comme une lettre à part ou si l'ordre de tri mettra œil entre ode et offre - et pas après (oui, il faut considérer œ comme équivalent de oe, pas comme une lettre entre o et p). Bon, vérification faite sur Postgres, l'ordre est correct, mais les "charts" ne le disent pas. A suivre...
L'idée n'est pas mauvaise, mais:
- ça ne dit pas ce qui se passe pour les caractères après 256 (qui ne sont pas dans la langue française mais qui peuvent apparaître dans des noms propres par exemple)
- ça ne détaille pas le comportement des caractères composés comme les ligatures (équivalence œ/oe par exemple)
Rapide test avec la collation utilisée précédemment:
testICU=# insert into t_accents2 (datum) values ('カタカナ');
INSERT 0 1
testICU=# select * from t_accents2 where datum = 'かたかな';
id | datum
--------+----------
100009 | カタカナ
(1 row)
testICU=# select * from t_accents2 where datum = 'かたか';
id | datum
----+-------
(0 rows)
Allez, pendant qu'on y est je vais même utiliser les caractères katakana demi-largeur:
testICU=# select * from t_accents2 where datum = 'カタカナ';
id | datum
--------+----------
100009 | カタカナ
(1 row)
満足ですか?
On peut modifier la requete pour aller au delà de 256 : modifier la limite dans la CTE, et utiliser NCHAR au lieu de CHAR.
et pour le classement des ligatures, le mieux c'est aussi de tester :
-->
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 WITH T(s) AS ( SELECT 'ode' COLLATE FRENCH_CI_AI UNION ALL SELECT 'offre' UNION ALL SELECT 'il' ) SELECT * FROM T ORDER BY s
ode œil offre
Sans doute, mais encore faut-il savoir ce qu'on cherche.
Au fait, il n'y a vraiment pas de méthode plus simple pour générer les valeurs de 1 à 256 dans SQL Server?
Genre avec Postgres on a generate_series(1, 256) alors c'est quoi l'équivalent en Transact SQL?
Certes mais vu le nombre de ligatures qui existent, le test peut prendre pas mal de temps. Je pense que la liste des ligatures prises en charge (et comment elles le sont!) gagnerait à être documenté quelque part.
Et donc que fait SQL Server dans le cas du like cité ici?
Je cite:
Donc, la question est: quelqu'un peut-il trouver une collation dans SQL Server équivalente à celle de l'exemple, et nous dire ce qu'elle fait dans le cas de la dernière requête?[...]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 CREATE COLLATION "nd3alt" ( provider = 'icu', locale='und(at)colAlternate=shifted', deterministic = false );
With the example above,
'abc. ...de' LIKE '%c,d%' COLLATE nd3altshould certainly be a match, but in the case of this variant:
'abc. ...de' LIKE '%c_d%' COLLATE nd3alt it's not necessarily clear how (or even if) it should work.
C'est pusillanime mais ...
... histoire de ne pas dire l'infini, quatre cent millions de collations ICU possibles, qui attendent juste d'être déclarées dans votre base.
Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 Collations : <a href="http://userguide.icu-project.org/locale" target="_blank">http://userguide.icu-project.org/locale</a> Locale x Script x Region_variant select count(*) from pg_collation where collprovider='i'; --> 734 Keyword ... ... calendar 7+ ... collation 6+ ... currency 2+ ... numbers 5+ Strength 4 Case_level 3 Case_first 4 Alternate 3 Variable_top n Normalization_checking 3 French 3 maxzor@mada:~$ python Python 2.7.17 (default, Nov 7 2019, 10:07:09) [GCC 9.2.1 20191008] on linux2 >>> 4*3*4*3*3*3*734*7*6*2*5 399530880
De ce que je comprends de l'exemple, je ne vois pas où se trouve le problème par rapport à l'implémentation du LIKE... '_' signifie 1 et 1 seul caractère. La collation ignore les ponctuations, mais pas les espaces. Il y a un et un seul espace entre c et d, donc je ne vois pas où se pose la question...
Quant au premier '%c,d%' je ne vois pas comment ça pourrait matcher, sans la mesure où les espaces sont ignorés, et que dans '%c,d%' il n'y a rien entre c et d d'après la collation...
L'exemple me semble bien bancale...
Ou alors la collation ignore aussi les espaces, et à l'inverse, le premier test est correct et le second faux, à nouveau sans équivoque !
Quant à une collation de SQL Server qui reproduire la même chose, je n'en vois pas.
En effet, les collations de SQL Server reprose sur des charset régionaux, (qui peuvent être des charsets "windows" ou "iso", notamment) auxquels on ajoute les 4 (si je ne me trompe pas) flag c, a, k et w.
Il n'y en a donc pas en effet qui traitent ce cas, donc difficile de répondre ce que pourrait faire SQL Server.
Par contre, j'ai fait un test sur les ligatures, qui me semble bien plus pertinent, car avant de conclure que finalement SQL Server avait raison, j'ai douté un moment de la logique du résultat :
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 with mots (mot) as ( select 'coeur' collate french_cs_ai union all select 'cur' ) select mot from mots where mot like '%c_e%'; mot ----- coeur
Je m'attendais à avoir les deux lignes retournées.
En effet, si la collation ignore les ligatures, et traite les "œ" comme "oe" alors le LIKE aurait dû retourner le "cœur" aussi bien que "coeur".
Alors naïvement, je me suis dit que c'était l'inverse, que les "oe" étaient considérés comme des "œ"... mais à ce moment, à l'inverse, le LIKE n'aurait pas dû retourner "coeur"...
Puis j'ai rallumé mon cerveau, et la logique m'a sauté aux yeux : dans "cœur", il n'y a pas de lettre entre le "c" et le "e", puisqu'il n'y a pas de "e". Tout simplement. La collation ne se contente pas de remplacer les caractères en cachette pour faire ses comparaisons, mais garde bien à l'esprit que même si "œ" peut être considéré comme "oe", il n'en reste pas moins un unique caractère, dont ni "o" ni "e" font, partie, uniquement les deux à la fois, tous les deux à la même position (le e n'est ni avant, ni après le o, il est à la même position).
Cette logique peut sembler déroutante, mais j'imagine que d'un point de vue littéraire, elle se tient.
Edit : d'ailleurs, en continuant ma réflexion, je me demande si la logique des collations de PostgreSQL ne pêche pas là : ne se contente-t-il pas simplement de "remplacer" les valeurs ignorées par celles à prendre en compte (comme le fait lower() ou unaccent()) plutôt que de traiter les caractères comme il se doit ? Ceci expliquerait effectivement cette contrainte avec le LIKE, puisqu'à ce moment, pas moyen de faire la différence entre coeur et cœur lors de traitements sur les sous-chaînes.
C'est heureux de votre part d'avoir relevé ce problème pour l'intérêt de cette discussion.
Il y a effectivement un problème de fonctionnalité côté postgres aujourd'hui avec les collations non-déterministes puisque l'opérateur like n'est pas supporté.
Il n'y a pas de collation non-déterministe hors-ICU, seulement les supplétifs unaccent, lower...
J'ai échangé avec Daniel Vérité qui a développé l'extension icu_ext. Quelques extraits :
Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
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 J'ai regardé un peu l'algo de LIKE actuel et pour moi, il faudrait faire complètement autre chose pour les collations non déterministes parce qu'on ne peut pas itérer sur les points de code, il faut se baser sur les résultats de recherches de sous-chaînes. Ensuite pour la question du motif underscore censé représenter un seul caractère, il faudrait prendre une position qui raisonnablement pourrait représenter un graphème, indépendamment de la collation. Par ailleurs je pense qu'un LIKE avec collation non déterministe ne sera jamais rapide, parce que l'API usearch_* d'ICU travaille en UTF-16, ce qui oblige à des conversions, et que de mémoire le usearch_find() d'ICU n'avait pas l'air intrinsèquement très rapide non plus. ------------------------------------------------------------------------------------------------------------------------------------ >> Est-ce que restreindre like '%%' avec ICU aux collations triviales vous >> paraît sensé comme solution temporaire? Pas vraiment parce que qui va se satisfaire d'un LIKE qui ne ferait pas mieux que strpos ou icu_strpos? Quel est très précisément le besoin en fait? Pour le moment l'expérience que je tire d'ICU dans le cadre de Postgres c'est que: - il y a quelques fonctions de bases vraiment très optimisées, comme la comparaison de chaînes en UTF8, ou la mise en forme normale des chaînes. - il y a d'autres fonctions très intéressantes pour une conformité parfaite avec Unicode et une bonne couverture fonctionnelle, mais coûteuses en temps d'exécution et déceptives à ce niveau par rapport à des solutions ad-hoc comme unaccent() et le type citext. ------------------------------------------------------------------------------------------------------------------------------------ >> Faire que >> select * from that where this like '%oe%' >> retourne coeur, COEUR, cur ... Si on utilise icu_ext c'est équivalent à WHERE icu_strpos(chaine, 'oe', 'und-u-ks-level1') > 0 donc fonctionnellement c'est déjà possible. >> L'envie est d'avoir à terme like pour les collations non-déterministes. Ce serait une bonne chose effectivement. De mon pt de vue il y a 2 possibilités ou étapes: - le faire dans icu_ext avec une fonction du genre is_like(string, pattern, [collation]) qui fonctionnerait indépendamment de la version de PG et serait dispo tout de suite. - le faire dans PG core avec l'opérateur LIKE et si c'est accepté ce serait pour PG13 au mieux et plus réalistement PG14.
Il est donc possible d'avoir une solution en l'état avec quelques défauts par rapport à like, qui je le comprends très bien peuvent être jugés rédhibitoires :
- pas de '%foo%bar%', ni de '%foo_bar%',
- pas d'indexation possible de la fonction, dont les performances sont en plus très basses.
Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 tidx=# explain (analyze, buffers) select distinct m from t where icu_strpos(m, 'coe', 'fr-u-ks-level1-kc-false') > 0 ; QUERY PLAN -------------------------------------------------------------------------------------------------------------------- HashAggregate (cost=133434.56..133508.04 rows=7348 width=5) (actual time=29704.525..29704.550 rows=24 loops=1) Group Key: m Buffers: shared hit=2336 read=13000 -> Seq Scan on t (cost=0.00..130867.20 rows=1026944 width=5) (actual time=64.874..29702.579 rows=1987 loops=1) Filter: (icu_strpos(m, 'coe'::text, 'fr-u-ks-level1-kc-false'::text) > 0) Rows Removed by Filter: 3078845 Buffers: shared hit=2336 read=13000 Planning Time: 0.101 ms JIT: Functions: 8 Options: Inlining false, Optimization false, Expressions true, Deforming true Timing: Generation 1.130 ms, Inlining 0.000 ms, Optimization 0.293 ms, Emission 5.104 ms, Total 6.527 ms Execution Time: 29705.743 ms
Voilà un rendu fidèle de mes investigations.
SQL Server fait mieux aujourd'hui, mais avec des collations beaucoup plus simples, n'ayant que 4 attributs (flags), et propriétaires.
Postgres a opté pour faire de la route avec le projet ICU, et propose ainsi un nombre de collations de plusieurs ordres de grandeur supérieur à celui de sqlserver, avec un nombre d'attributs (11) plus important.
Je ne pense pas, j'ai lu postgresql/src/backend/utils/adt/like_match.c : ca a été développé pour les collations déterministes. Une réécriture plus ou moins complète est à prévoir. C'est compréhensible, ICU est arrivé officiellement dans postgres depuis quelques mois.
Proposer une solution générale au problème de la recherche de sous-chaîne (like) sur des collations ICU non-déterministes est assez complexe, mais probablement pas infaisable. Le temps dira si le choix fait par l'équipe postgres de partir sur une base bien plus riche paie, avec des fonctionnalités immensément supérieures si ce problème est résolu ; ou bien si l'approche sqlserver d'utiliser des collations non-déterministes triviales, et de ne pas s'embourber de complexité, est la bonne. M'est avis que le temps est compté avant que sqlserver n'adopte l'approche ICU, ne serait-ce que parce que les ingénieurs de Redmond ne peuvent pas rivaliser avec l'aura du consortium Unicode.
PostgreSQL supporte tout ce que vous venez d'évoquer, les formes fléchies (inflected form ou stemming en anglais), la recherches de synonymes et de traductions.
Plus la recherche floue - fuzzing et une indexation performante avec GIN, GIST, SP-GIST.
Très bonne question, je me la pose aussi. Beaucoup de gens que je croise dans les SI collent sans se poser de question la stack ELK à toutes les sauces, parce que ça fait branché. Ca serait intéressant d'avoir un avis d'expert sur l'overlap et les différences entre SGBD et moteurs de recherche textuelle.
Ca me fait penser, sur un sujet connexe, au mantra "microsoft est incontournable en BI parce que les cubes OLAP", qui est, si on creuse profondément du vent.
C'est loin d'être évident pour moi et je ne vois pas encore de killer feature côté elasticsearch, que je connais mal.
Les stopwords, les synonymes, les fautes, la distance (Levenshtein notamment), tout ça est faisable sur postgres.
Je suis surpris par ce passage :
Pour le coup, ça donne raison à Microsoft d'avoir, depuis le début, pris le problème à l'envers : Windows travaille nativement (depuis la version 2000 il me semble) en UTF-16 (ou UNICODE, qui sont synonymes) et, au prix d'une occupation mémoire supérieure (le double si on reste dans des encodages sur 1 octet, un peu moins si on travaille avec des encodages de taille variable comme UTF-8). SQL Server peut travailler directement en UTF-16 avec les types NCHAR et NVARCHAR.Par ailleurs je pense qu'un LIKE avec collation non déterministe ne sera jamais rapide, parce que l'API usearch_* d'ICU travaille en UTF-16, ce qui oblige à des conversions
En effet, l'avantage d'UNICODE, c'est qu'il permet, à ce jour, de représenter l'ensemble de tous les glyphes de tous les alphabets mondiaux, et tant qu'à faire, d'autres (smileys, etc.) sans devoir adapter l'encodage.
On se retrouve avec des manipulations de chaînes bien plus simples, et au final bien plus performantes malgré une consommation supérieure de mémoire.
Et je te rejoint sur la probable future intégration d'ICU dans SQL Server, avec cet avantage qu'il n'y aura pas ces conversions coûteuses à faire entre le stockage des données et leur manipulation.
Je te voyais venir à 10 000 en écrivant mon post
C'est possible, je ne sais pas.
https://utf8everywhere.org/
J'ai cherché quelques heures des mesures des pénalités côté traitement de l'UTF8 par rapport à UTF16 sans rien trouver de probant.
Par contre c'est sûr que côté occupation mémoire et stockage, les performances d'UTF16 sont désastreuses, dans nos langues latines deux fois moindres.
P.S. depuis le lien : "ICU uses UTF-16 for historical reasons, thus it is quite hard to measure."
Donc si ICU travaille comme les gens sensés en UTF8 ca va.
Non, Unicode c'est la spécification, UTF8, UTF16, UTF32... sont des implémentations.
Merci pour vos réponses sur les traitements intégralement en BDD*vs outils dédiés.
Pour moi il y a un défaut de connaissance du développeur lambda sur ces possibilités au sein d'un SGBD. Je ne sais pas depuis quand ce genre de traitement est possible avec postgresq, mais j'en étais resté à l'information «*une simple recherche fulltext est plusieurs ordres de grandeurs plus lente avec un SGBD*qu'avec un outil dédié*». Je ne sais absolument pas si c'est toujours le cas aujourd'hui.Les stopwords, les synonymes, les fautes, la distance (Levenshtein notamment), tout ça est faisable sur postgres.
Déjà répondu :
https://www.developpez.net/forums/d2.../#post11383551
La notion de "non deterministic" dans postGreSQL est même sérieusement imbécile ! Rien à voir avec un comportement non déterministe...
A +
Il y a d'autres problèmes sur ces nouvelles collations avec PostgreSQL. Elles sont visiblement incapable de fonctionner correctement avec la plupart des opérateurs et fonctions.
Un petit exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 CREATE COLLATION ignore_accents (provider = icu, locale = 'fr-u-ks-level1-kc-false', deterministic=false); CREATE TABLE T_MOT(ID SERIAL PRIMARY KEY, MOT VARCHAR(32) COLLATE ignore_accents); INSERT INTO T_MOT (MOT) VALUES ('veau'), ('vache'), ('cochon'), ('éléphant');Ne renvoie rien !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 SELECT * FROM T_MOT WHERE MOT = 'elephant'
Ne renvoie que le veau !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 SELECT * FROM T_MOT WHERE MOT IN ('veau', 'elephant')
Donc on se demande à quoi servent ces collations !
Pour info : PostgreSQL 12.2, compiled by Visual C++ build 1914, 64-bit
Sous WIndows 10
A +
Je plussois à la chose. Microsoft à dit dès le début que UTF 8 était un scandale pour toutes les langues non latines... Cela allait immanquablement générale de multiples problèmes de performances laissant toutes les langues sauf l'anglais sur le carreau. MS n'a pas voulu pendant très longtemps de l'UTF8... Ils viennent enfin de le mettre, mais cela n'est pas une bonne chose. La masse populaire, bien crétine veut de l'UTF8.... très bien, faisons comme marie Antoinette !!! Puisqu'ils n'ont pas de pain, qu'ils mangent des brioches....
Hélas
J'en doute fortement. Le principe chez MS est de toucher le moins possible au moteur de stockage, pour deux raisons :Et je te rejoint sur la probable future intégration d'ICU dans SQL Server, avec cet avantage qu'il n'y aura pas ces conversions coûteuses à faire entre le stockage des données et leur manipulation.
1) en cas de bug une corruption des données peut arriver.
2) les performances basiques de traitement des requêtes se jouent au niveau de l'accès aux données. MS est actuellement le plus fort à ce jeu là devant Oracle, comme MySQL et PostGreSQL ICU remettrait en question ces performances...
A +
Déjà dit, mais c'est vrai que, depuis que tu as chié sur le topic, c'est plus dur à lire.
Non, aucun problème avec les constructeurs de lignes multivaluées sur linux :
Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 tidx=# select distinct m from t where m collate fr_ci_ai in ('veau','elephant'); m ---------- éléphant Veau veau (3 lignes) tidx=#
Il faudrait déjà se mettre d'accord sur le benchmark... Mais je suis tout à fait d'accord. Attendez simplement la fin de mon article (quelques mois) pour y voir plus clair. Il fait déjà près de 100 pages et devrait doubler !
On m'a beaucoup critiqué et déformé mes propos. Pour information, j'ai parlé de simple test, et je vous invite à relire l'article initial :
https://www.developpez.net/forums/d2.../#post11357084
Que certains ont transformé en "benchmark", alors que ce n'était pas le cas, et se permettant de m'assassiner en disant que mes benchmark étaient pourris :
sodium : https://www.developpez.net/forums/d2.../#post11358578
fredoche : https://www.developpez.net/forums/d2.../#post11360654
...
Cela ressemble fort à ce que l'on pratique dans les dictatures communistes !
A +
testé sous Windows :
ERROR: ERREUR: le collationnement « fr_ci_ai » pour l'encodage « UTF8 » n'existe pas
Code : Sélectionner tout - Visualiser dans une fenêtre à part select distinct MOT from T_MOT where MOT collate fr_ci_ai
LINE 1: select distinct MOT from T_MOT where MOT collate fr_ci_ai
^
SQL state: 42704
Character: 42
Donc des résultats différents sous Linux et Windows... C'est encore pire que ce que je croyais !
A +
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager