ClickHouse / clickhouse-odbc

ODBC driver for ClickHouse
https://clickhouse.tech
Apache License 2.0
247 stars 88 forks source link

Проблема с Tableau. #318

Closed bun4uk closed 3 years ago

bun4uk commented 4 years ago

При работе с Custom Query в Tableau есть один очень неудобный момент. Если SQL с синтаксической ошибкой, либо не рабочий – Tableau грузит его без остановки и не выдает ошибку о том, что запрос не компилируется. И приходиться убивать табло файл и начинать все сначала. Если SQL без синтаксических ошибок и написан правильно – Tableau не просто компилирует и собирает метадату, а обрабатывает весь запрос – а это сильно влияет на время выполнения команды. Раньше использовали вертику и там Custom queries создавались моментально. С кликхаусом это становится не очень удобно, к сожалению. Возможно ли как-то настроить драйвер, чтобы создавать custom queries для tableau не дожидаясь прогрузки всего запроса?

traceon commented 4 years ago

При SQL с синтаксической ошибкой, мне Tableau выдает HTTP status code: 400 Received error: ... ошибку от сервера о плохом синтаксисе.

При SQL SELECT * FROM hits_100m_obfuscated на сервере play-api.clickhouse.tech, Custom SQL появляется сразу, и данные не извлекаются, если не нажать Update Now/Automatically Update.

Если возможно, опишите пошагово, что и как делать, и что не так, и как хочется, чтоб было, используя DSN, ссылающийся на сервер https://clickhouse.tech/docs/en/getting-started/playground/ например.

bun4uk commented 4 years ago

@traceon почему-то не получилось из-под Tableau подключиться к playground. Использовали нашу бд.

Записали видео где видно как изменение SQL в custom query приводит к извлечению данных и долгой загрузке. https://www.youtube.com/watch?v=91XXFb8kOgU

На втором видео видно как внесение ошибки в SQL приводит к бесконечной загрузке. https://www.youtube.com/watch?v=k9AUm6IbBfU

traceon commented 4 years ago

Единственную проблему, которую я увидел - это долгий Loading Metadata.

На втором видео вы не подождали пока это не завершится и Tableau не покажет строку с ошибкой от ClickHouse сервера.

Примерно так же будет если написать SELECT 1, и SEL_x_ECT 1.

traceon commented 4 years ago

https://community.tableau.com/s/question/0D54T00000C5nNn/tableau-taking-long-time-for-loading-metadata-while-creating-data-connection

https://community.tableau.com/s/question/0D54T00000C5bl7/connection-stuck-in-loading-metadata (посмотрите "Лучший ответ")

bun4uk commented 4 years ago

спасибо, почитаю посты p.s. на втором видео я не стал дожидаться ошибки сервера, так как она не приходит. Запрос грузится вечность и приходится закрывать табло-файл

bun4uk commented 4 years ago

@traceon пробую подключиться из Tableau к play-api.clickhouse.tech. При попытке :

An error occurred while communicating with Other Databases (ODBC)
Bad Connection: Tableau could not connect to the data source.
Error Code: B19090E0
SSL Exception: error:14007086:SSL routines:CONNECT_CR_CERT:certificate verify failed

Настройки DSN сейчас такие:

CleanShot 2020-10-06 at 11 58 02@2x

Также пробовал дополнительно указать Proto: https и SSLMode: allow. Ошибка не пропала. Где я мог ошибиться в конфиге?

traceon commented 4 years ago

@bun4uk какая версия драйвера?

bun4uk commented 4 years ago

@traceon последняя 1.1.8

traceon commented 4 years ago

С драйвером с мастера:

$ cat ~/.odbc.ini
...
[ClickHouse DSN (dev)]
Driver        = ClickHouse ODBC Driver (ANSI)
Description   = ClickHouse DSN (dev)
Url           = https://playground:clickhouse@play-api.clickhouse.tech:8443/query?database=system
Host          = play-api.clickhouse.tech
Port          = 8443
Path          = /query
Database      = system
Username      = playground
Password      = clickhouse
CALocation    = /usr/local/etc/openssl@1.1/cert.pem
Timeout       = 3
$ iusql "ClickHouse DSN (dev)"
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> SELECT 1
+----+
| 1  |
+----+
| 1  |
+----+

SQLRowCount returns 1
1 rows fetched
traceon commented 4 years ago

@bun4uk Скорее всего, вам нужно указать CALocation = /usr/local/etc/openssl@1.1/cert.pem в DSN.

bun4uk commented 4 years ago

Спасибо! Получилось подключиться.

Я разобрался в каком случае зависает выполнение запроса с ошибкой в синтаксисе. Если установить большой Timeout в DSN конфиге, то процессинг запроса не упадет до тех пор, пока не закончится таймаут.

Steps to reproduce:

bun4uk commented 4 years ago

Также проверил логи кликхауса. Кликхаус сразу же бросает exception после попытки выполнения неправильного запроса из окна Edit Custom SQL. В то время, как модальное окно в Tableau продолжает загрузку, пока не закончится Timeout, и только потом выдает ошибку.

Иными словами:

traceon commented 4 years ago

Ну это, собственно, та проблема с "loading metadata". Ссылки на обсуждения, почему это так работает в Табло я привел выше. Не думаю, что что-то можно сделать на уровне драйвера, чтоб обойти это.

yurifal commented 4 years ago

Создайте вот такой файл кастомизации ODBC соединения для Tableau по месту ~/.Documents/My Tableau Repository/Datasources/clickhouse.tdc

<?xml version='1.0' encoding='utf-8' ?>
<connection-customization class='genericodbc' enabled='true' version='18.1'>
    <vendor name='ClickHouse' />
    <driver name='ClickHouse Driver' />
    <customizations>
        <customization name='CAP_CONNECT_STORED_PROCEDURE' value='no' />
        <customization name='CAP_CREATE_TEMP_TABLES' value='no' />
        <customization name='CAP_QUERY_GROUP_BY_ALIAS' value='no' />
        <customization name='CAP_QUERY_GROUP_BY_DEGREE' value='no' />
        <customization name='CAP_QUERY_INOUT_JOINS' value='no' />
        <customization name='CAP_QUERY_JOIN_PUSH_DOWN_CONDITION_EXPRESSIONS' value='yes' />
        <customization name='CAP_QUERY_JOIN_REQUIRES_SUBQUERY' value='yes' />
        <customization name='CAP_QUERY_SORT_BY_DEGREE' value='no' />
        <customization name='CAP_QUERY_WHERE_FALSE_METADATA' value='yes' />
        <customization name='CAP_SELECT_INTO' value='no' />
        <customization name='CAP_SELECT_TOP_INTO' value='no' />
    </customizations>
</connection-customization>

и перезапустите Tableau Desktop.

traceon commented 4 years ago

@yurifal Спасибо, тут исправление проблемы с метадатой или еще что-то?

Добавлю, что <driver name='ClickHouse Driver' /> должен точно совпадать с именем драйвера, для которого создан используемый DSN.

yurifal commented 4 years ago

@yurifal Спасибо, тут исправление проблемы с метадатой или еще что-то?

по моим представлениям вот эта настройка добавляет в метадата-запросы нужный WHERE:

<customization name='CAP_QUERY_WHERE_FALSE_METADATA' value='yes' />

Три настройки ("стандартные" для ODBC драйверов многих других СУБД) явно запрещают создание времянок и операции с ними:

        <customization name='CAP_CREATE_TEMP_TABLES' value='no' />
        <customization name='CAP_SELECT_INTO' value='no' />
        <customization name='CAP_SELECT_TOP_INTO' value='no' />

Остальные настройки взяты из файла, который уже есть в проекте:

https://github.com/ClickHouse/clickhouse-odbc/blob/master/packaging/clickhouse-odbc.tdc.sample

bun4uk commented 4 years ago

@yurifal Спасибо! Добавил этот файл, как вы описали. Имя драйвера указал своё. К сожалению, не не увидел изменений. Попытка ввода SQL с синтаксической ошибкой ждет окончания таймаута, перед показом самой ошибки.

CleanShot 2020-10-07 at 11 10 26@2x

CleanShot 2020-10-07 at 11 13 05@2x CleanShot 2020-10-07 at 11 17 22@2x

CleanShot 2020-10-07 at 11 28 42@2x

yurifal commented 4 years ago

1) в логе Табло (в папке Logs файл log.txt) есть ли вот такой текст

found **matching** TDC

? Если есть -- то OK. Если нет -- значит TDC не подтягивается, и тогда нужно пере-проверять имя драйвера.

2) Какой timeout выставлен в odbc.ini ? у меня 3 (секунды). Если взять Ваш пример, то у меня через секунд 5 вываливается вот такая ошибка:

Screenshot 2020-10-07 at 13 55 34
bun4uk commented 4 years ago

@yurifal в log.txt видно что TDC подтянулся.

{"ts":"2020-10-07T11:07:46.310","pid":91705,"tid":"c3997e","sev":"info","req":"-","sess":"-","site":"-","user":"-","k":"msg","v":"Found matching TDC '/Users/bunchukv/Documents/My Tableau Repository/Datasources/clickhouse.tdc' for class='genericodbc', vendor='ClickHouse', and driver='clickhouse'."}

Таймаут стоит 1000. Меньше не можем поставить, так как есть запрос от аналитиков. Соотсветсвенно ошибка (такая как вы в показали скриншоте) появляется где-то на 1005ой секунде, что ну очень неудобно. Хотя, если посмотреть логи самого кликхауса, то там эта ошибка появляется сразу же после попытки создать Custom SQL.

Если я поставлю таймаут в 3 секунды, то большая часть дашбордов перестанет работать.

yurifal commented 4 years ago

Если Custom SQL синтаксически правильный, то Табло возвращает контроль сразу.

Может на этапе создания / правки источников (для работы в Data Pane с Custom SQL) использовать копию DSN но с Timeout = 3 (или сколько будет удобно для отладки кода), а потом в prod сменить DSN и публиковать?

bun4uk commented 4 years ago

@yurifal Спасибо большое! Такой вариант, в принципе, +- примелим. Немного иначе правда сделали. В настройках DSN оставил Timeout=1000. А в конфиге соединения для Табло руками прописали Timeout=10. Для этапа создания Custom SQL этого достаточно. CleanShot 2020-10-07 at 15 40 01@2x

dmserg commented 3 years ago

Это кстати легко воспроизводится из test\test.py скрипта. Достаточно добавить в connection string у pyodbc.connect ";TIMEOUT=300" и выполнить запрос query("select * from system.nonexisting")

Скрипт будет висеть 5 минут, в драйвере залипает вызов SQLFreeStmt.

dmserg commented 3 years ago

У меня получилось пофиксать эту проблему - https://github.com/ClickHouse/clickhouse-odbc/pull/326 Проверял через pyodbc и на Tableau. Посмотрите плз - нет ли тут еще каких-то подводных камней?

filimonov commented 3 years ago

Это кстати легко воспроизводится из test\test.py скрипта. Достаточно добавить в connection string у pyodbc.connect ";TIMEOUT=300" и выполнить запрос query("select * from system.nonexisting")

Скрипт будет висеть 5 минут, в драйвере залипает вызов SQLFreeStmt.

Может быть попробуете добавить такой тест?

dmserg commented 3 years ago

Может быть попробуете добавить такой тест?

В виде питон скрипта легко, а в интеграционных gtest тесты пока не нашел как легко это воспроизвести - в существующем тестовом фреймворке метод closeCursor() никогда не заходит в условие if (connection.session && response && in). Но это легко воспроизводится в связке с ODBC клиентом - например Tableau или pyodbc.

filimonov commented 3 years ago

Да, у нас уже есть тесты в питоне - можно добавить туда https://github.com/ClickHouse/clickhouse-odbc/blob/master/test/test.py https://github.com/ClickHouse/clickhouse-odbc/tree/master/test/parameterized

dmserg commented 3 years ago

Кстати интересное наблюдение - это не воспроизводится если делать для pyodbc явный вызов connection.close(), но воспроизводится если оставить очистку ресурсов на выходе контекста with (через __exit__) либо при окончании выполнения скрипта. Что наводит на мысли о не очень корректном обращении с коннекшеном в Tableau.

dmserg commented 3 years ago

Да, у нас уже есть тесты в питоне - можно добавить туда https://github.com/ClickHouse/clickhouse-odbc/blob/master/test/test.py https://github.com/ClickHouse/clickhouse-odbc/tree/master/test/parameterized

добавленный тест понятен, подходит?

filimonov commented 3 years ago

Да, у нас уже есть тесты в питоне - можно добавить туда https://github.com/ClickHouse/clickhouse-odbc/blob/master/test/test.py https://github.com/ClickHouse/clickhouse-odbc/tree/master/test/parameterized

добавленный тест понятен, подходит?

Да, все выглядит хорошо. Спасибо!