Merge branch 'master' into codecs_for_nested_types

This commit is contained in:
alesapin 2020-09-22 09:52:31 +03:00
commit b57708c3dd
52 changed files with 797 additions and 214 deletions

View File

@ -80,6 +80,11 @@ endif ()
include (cmake/find/ccache.cmake)
option(ENABLE_CHECK_HEAVY_BUILDS "Don't allow C++ translation units to compile too long or to take too much memory while compiling" OFF)
if (ENABLE_CHECK_HEAVY_BUILDS)
set (CMAKE_CXX_COMPILER_LAUNCHER prlimit --rss=10000000 --cpu=600)
endif ()
if (NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "None")
set (CMAKE_BUILD_TYPE "RelWithDebInfo")
message (STATUS "CMAKE_BUILD_TYPE is not set, set to default = ${CMAKE_BUILD_TYPE}")

120
benchmark/hardware.sh Executable file
View File

@ -0,0 +1,120 @@
#!/bin/bash -e
if [[ -n $1 ]]; then
SCALE=$1
else
SCALE=100
fi
TABLE="hits_${SCALE}m_obfuscated"
DATASET="${TABLE}_v1.tar.xz"
QUERIES_FILE="queries.sql"
TRIES=3
AMD64_BIN_URL="https://clickhouse-builds.s3.yandex.net/0/e29c4c3cc47ab2a6c4516486c1b77d57e7d42643/clickhouse_build_check/gcc-10_relwithdebuginfo_none_bundled_unsplitted_disable_False_binary/clickhouse"
AARCH64_BIN_URL="https://clickhouse-builds.s3.yandex.net/0/e29c4c3cc47ab2a6c4516486c1b77d57e7d42643/clickhouse_special_build_check/clang-10-aarch64_relwithdebuginfo_none_bundled_unsplitted_disable_False_binary/clickhouse"
FASTER_DOWNLOAD=wget
if command -v axel >/dev/null; then
FASTER_DOWNLOAD=axel
else
echo "It's recommended to install 'axel' for faster downloads."
fi
if command -v pixz >/dev/null; then
TAR_PARAMS='-Ipixz'
else
echo "It's recommended to install 'pixz' for faster decompression of the dataset."
fi
mkdir -p clickhouse-benchmark-$SCALE
pushd clickhouse-benchmark-$SCALE
if [[ ! -f clickhouse ]]; then
CPU=$(uname -m)
if [[ ($CPU == x86_64) || ($CPU == amd64) ]]; then
$FASTER_DOWNLOAD "$AMD64_BIN_URL"
elif [[ $CPU == aarch64 ]]; then
$FASTER_DOWNLOAD "$AARCH64_BIN_URL"
else
echo "Unsupported CPU type: $CPU"
exit 1
fi
fi
chmod a+x clickhouse
if [[ ! -f $QUERIES_FILE ]]; then
wget "https://raw.githubusercontent.com/ClickHouse/ClickHouse/master/benchmark/clickhouse/$QUERIES_FILE"
fi
if [[ ! -d data ]]; then
if [[ ! -f $DATASET ]]; then
$FASTER_DOWNLOAD "https://clickhouse-datasets.s3.yandex.net/hits/partitions/$DATASET"
fi
tar $TAR_PARAMS --strip-components=1 --directory=. -x -v -f $DATASET
fi
echo "Starting clickhouse-server"
./clickhouse server > server.log 2>&1 &
PID=$!
function finish {
kill $PID
wait
}
trap finish EXIT
echo "Waiting for clickhouse-server to start"
for i in {1..30}; do
sleep 1
./clickhouse client --query "SELECT 'The dataset size is: ', count() FROM $TABLE" 2>/dev/null && break || echo '.'
if [[ $i == 30 ]]; then exit 1; fi
done
echo
echo "Will perform benchmark. Results:"
echo
cat "$QUERIES_FILE" | sed "s/{table}/${TABLE}/g" | while read query; do
sync
echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null
echo -n "["
for i in $(seq 1 $TRIES); do
RES=$(./clickhouse client --max_memory_usage 100000000000 --time --format=Null --query="$query" 2>&1)
[[ "$?" == "0" ]] && echo -n "${RES}" || echo -n "null"
[[ "$i" != $TRIES ]] && echo -n ", "
done
echo "],"
done
echo
echo "Benchmark complete. System info:"
echo
echo '----Version and build id--------'
./clickhouse local --query "SELECT version(), buildId()"
echo '----CPU-------------------------'
lscpu
echo '----Block Devices---------------'
lsblk
echo '----Disk Free and Total--------'
df -h .
echo '----Memory Free and Total-------'
free -h
echo '----Physical Memory Amount------'
cat /proc/meminfo | grep MemTotal
echo '----RAID Info-------------------'
cat /proc/mdstat
#echo '----PCI-------------------------'
#lspci
#echo '----All Hardware Info-----------'
#lshw
echo '--------------------------------'
echo

View File

@ -17,7 +17,7 @@ ccache --show-stats ||:
ccache --zero-stats ||:
ln -s /usr/lib/x86_64-linux-gnu/libOpenCL.so.1.0.0 /usr/lib/libOpenCL.so ||:
rm -f CMakeCache.txt
cmake --debug-trycompile --verbose=1 -DCMAKE_VERBOSE_MAKEFILE=1 -LA -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSANITIZE=$SANITIZER $CMAKE_FLAGS ..
cmake --debug-trycompile --verbose=1 -DCMAKE_VERBOSE_MAKEFILE=1 -LA -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSANITIZE=$SANITIZER -DENABLE_CHECK_HEAVY_BUILDS=1 $CMAKE_FLAGS ..
ninja $NINJA_FLAGS clickhouse-bundle
mv ./programs/clickhouse* /output
mv ./src/unit_tests_dbms /output ||: # may not exist for some binary builds

View File

@ -1,7 +1,7 @@
# docker build -t yandex/clickhouse-test-base .
FROM ubuntu:19.10
ENV DEBIAN_FRONTEND=noninteractive LLVM_VERSION=10
ENV DEBIAN_FRONTEND=noninteractive LLVM_VERSION=11
RUN apt-get update \
&& apt-get install ca-certificates lsb-release wget gnupg apt-transport-https \
@ -43,7 +43,6 @@ RUN apt-get update \
llvm-${LLVM_VERSION} \
moreutils \
perl \
perl \
pigz \
pkg-config \
tzdata \

View File

@ -1,5 +1,5 @@
# docker build -t yandex/clickhouse-integration-test .
FROM ubuntu:19.10
FROM yandex/clickhouse-test-base
RUN apt-get update \
&& env DEBIAN_FRONTEND=noninteractive apt-get -y install \
@ -8,7 +8,6 @@ RUN apt-get update \
libreadline-dev \
libicu-dev \
bsdutils \
llvm-9 \
gdb \
unixodbc \
odbcinst \
@ -29,9 +28,3 @@ RUN curl 'https://cdn.mysql.com//Downloads/Connector-ODBC/8.0/mysql-connector-od
ENV TZ=Europe/Moscow
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# Sanitizer options
RUN echo "TSAN_OPTIONS='verbosity=1000 halt_on_error=1 history_size=7'" >> /etc/environment; \
echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment; \
echo "MSAN_OPTIONS='abort_on_error=1'" >> /etc/environment; \
ln -s /usr/lib/llvm-9/bin/llvm-symbolizer /usr/bin/llvm-symbolizer;

View File

@ -29,7 +29,7 @@ RUN apt-get update \
tzdata \
vim \
wget \
&& pip3 --no-cache-dir install clickhouse_driver \
&& pip3 --no-cache-dir install clickhouse_driver scipy \
&& apt-get purge --yes python3-dev g++ \
&& apt-get autoremove --yes \
&& apt-get clean \

View File

@ -45,7 +45,7 @@ Action required for every item -- these are errors that must be fixed.
This table shows queries that take significantly longer to process on the client than on the server. A possible reason might be sending too much data to the client, e.g., a forgotten `format Null`.
#### Inconsistent Short Marking
#### Unexpected Query Duration
Action required for every item -- these are errors that must be fixed.
Queries that have "short" duration (on the order of 0.1 s) can't be reliably tested in a normal way, where we perform a small (about ten) measurements for each server, because the signal-to-noise ratio is much smaller. There is a special mode for such queries that instead runs them for a fixed amount of time, normally with much higher number of measurements (up to thousands). This mode must be explicitly enabled by the test author to avoid accidental errors. It must be used only for queries that are meant to complete "immediately", such as `select count(*)`. If your query is not supposed to be "immediate", try to make it run longer, by e.g. processing more data.

View File

@ -688,12 +688,13 @@ create view shortness
-- Report of queries that have inconsistent 'short' markings:
-- 1) have short duration, but are not marked as 'short'
-- 2) the reverse -- marked 'short' but take too long.
-- The threshold for 2) is twice the threshold for 1), to avoid jitter.
-- The threshold for 2) is significantly larger than the threshold for 1), to
-- avoid jitter.
create table inconsistent_short_marking_report
engine File(TSV, 'report/inconsistent-short-marking.tsv')
engine File(TSV, 'report/unexpected-query-duration.tsv')
as select
multiIf(marked_short and time > 0.1, 'marked as short but is too long',
not marked_short and time < 0.02, 'is short but not marked as such',
multiIf(marked_short and time > 0.1, '"short" queries must run faster than 0.02 s',
not marked_short and time < 0.02, '"normal" queries must run longer than 0.1 s',
'') problem,
marked_short, time,
test, query_index, query_display_name

View File

@ -1,8 +1,6 @@
<yandex>
<profiles>
<default>
<query_profiler_real_time_period_ns>10000000</query_profiler_real_time_period_ns>
<query_profiler_cpu_time_period_ns>0</query_profiler_cpu_time_period_ns>
<allow_introspection_functions>1</allow_introspection_functions>
<log_queries>1</log_queries>
<metrics_perf_events_enabled>1</metrics_perf_events_enabled>

View File

@ -15,6 +15,7 @@ import sys
import time
import traceback
import xml.etree.ElementTree as et
from scipy import stats
def tsv_escape(s):
return s.replace('\\', '\\\\').replace('\t', '\\t').replace('\n', '\\n').replace('\r','')
@ -211,7 +212,8 @@ for query_index in queries_to_run:
for conn_index, c in enumerate(all_connections):
try:
prewarm_id = f'{query_prefix}.prewarm0'
res = c.execute(q, query_id = prewarm_id)
# Will also detect too long queries during warmup stage
res = c.execute(q, query_id = prewarm_id, settings = {'max_execution_time': 10})
print(f'prewarm\t{query_index}\t{prewarm_id}\t{conn_index}\t{c.last_query.elapsed}')
except KeyboardInterrupt:
raise
@ -221,7 +223,6 @@ for query_index in queries_to_run:
query_error_on_connection[conn_index] = traceback.format_exc();
continue
# Report all errors that ocurred during prewarm and decide what to do next.
# If prewarm fails for the query on all servers -- skip the query and
# continue testing the next query.
@ -246,7 +247,14 @@ for query_index in queries_to_run:
# sending excessive data.
start_seconds = time.perf_counter()
server_seconds = 0
profile_seconds = 0
run = 0
# Arrays of run times for each connection.
all_server_times = []
for conn_index, c in enumerate(this_query_connections):
all_server_times.append([])
while True:
run_id = f'{query_prefix}.run{run}'
@ -259,14 +267,17 @@ for query_index in queries_to_run:
e.message = run_id + ': ' + e.message
raise
server_seconds += c.last_query.elapsed
print(f'query\t{query_index}\t{run_id}\t{conn_index}\t{c.last_query.elapsed}')
elapsed = c.last_query.elapsed
all_server_times[conn_index].append(elapsed)
if c.last_query.elapsed > 10:
server_seconds += elapsed
print(f'query\t{query_index}\t{run_id}\t{conn_index}\t{elapsed}')
if elapsed > 10:
# Stop processing pathologically slow queries, to avoid timing out
# the entire test task. This shouldn't really happen, so we don't
# need much handling for this case and can just exit.
print(f'The query no. {query_index} is taking too long to run ({c.last_query.elapsed} s)', file=sys.stderr)
print(f'The query no. {query_index} is taking too long to run ({elapsed} s)', file=sys.stderr)
exit(2)
# Be careful with the counter, after this line it's the next iteration
@ -297,6 +308,35 @@ for query_index in queries_to_run:
client_seconds = time.perf_counter() - start_seconds
print(f'client-time\t{query_index}\t{client_seconds}\t{server_seconds}')
#print(all_server_times)
#print(stats.ttest_ind(all_server_times[0], all_server_times[1], equal_var = False).pvalue)
# Run additional profiling queries to collect profile data, but only if test times appeared to be different.
# We have to do it after normal runs because otherwise it will affect test statistics too much
if len(all_server_times) == 2 and stats.ttest_ind(all_server_times[0], all_server_times[1], equal_var = False).pvalue < 0.1:
run = 0
while True:
run_id = f'{query_prefix}.profile{run}'
for conn_index, c in enumerate(this_query_connections):
try:
res = c.execute(q, query_id = run_id, settings = {'query_profiler_real_time_period_ns': 10000000})
print(f'profile\t{query_index}\t{run_id}\t{conn_index}\t{c.last_query.elapsed}')
except Exception as e:
# Add query id to the exception to make debugging easier.
e.args = (run_id, *e.args)
e.message = run_id + ': ' + e.message
raise
elapsed = c.last_query.elapsed
profile_seconds += elapsed
run += 1
# Don't spend too much time for profile runs
if run > args.runs or profile_seconds > 10:
break
# And don't bother with short queries
# Run drop queries
drop_queries = substitute_parameters(drop_query_templates)
for conn_index, c in enumerate(all_connections):

View File

@ -98,9 +98,9 @@ th {{
tr:nth-child(odd) td {{filter: brightness(90%);}}
.inconsistent-short-marking tr :nth-child(2),
.inconsistent-short-marking tr :nth-child(3),
.inconsistent-short-marking tr :nth-child(5),
.unexpected-query-duration tr :nth-child(2),
.unexpected-query-duration tr :nth-child(3),
.unexpected-query-duration tr :nth-child(5),
.all-query-times tr :nth-child(1),
.all-query-times tr :nth-child(2),
.all-query-times tr :nth-child(3),
@ -325,13 +325,13 @@ if args.report == 'main':
if slow_on_client_rows:
errors_explained.append([f'<a href="#{currentTableAnchor()}">Some queries are taking noticeable time client-side (missing `FORMAT Null`?)</a>']);
unmarked_short_rows = tsvRows('report/inconsistent-short-marking.tsv')
unmarked_short_rows = tsvRows('report/unexpected-query-duration.tsv')
error_tests += len(unmarked_short_rows)
addSimpleTable('Inconsistent Short Marking',
['Problem', 'Is marked as short', 'New client time, s', 'Test', '#', 'Query'],
addSimpleTable('Unexpected Query Duration',
['Problem', 'Marked as "short"?', 'Run time, s', 'Test', '#', 'Query'],
unmarked_short_rows)
if unmarked_short_rows:
errors_explained.append([f'<a href="#{currentTableAnchor()}">Some queries have inconsistent short marking</a>']);
errors_explained.append([f'<a href="#{currentTableAnchor()}">Some queries have unexpected duration</a>']);
def add_partial():
rows = tsvRows('report/partial-queries-report.tsv')

View File

@ -48,13 +48,6 @@ fi
ln -sf /usr/share/clickhouse-test/config/client_config.xml /etc/clickhouse-client/config.xml
echo "TSAN_OPTIONS='verbosity=1000 halt_on_error=1 history_size=7'" >> /etc/environment
echo "TSAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment
echo "ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "LLVM_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
service zookeeper start
sleep 5
service clickhouse-server start && sleep 5

View File

@ -48,13 +48,6 @@ fi
ln -sf /usr/share/clickhouse-test/config/client_config.xml /etc/clickhouse-client/config.xml
echo "TSAN_OPTIONS='verbosity=1000 halt_on_error=1 history_size=7'" >> /etc/environment
echo "TSAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment
echo "ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "LLVM_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
service zookeeper start
sleep 5
service clickhouse-server start && sleep 5

View File

@ -43,8 +43,6 @@ ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/u
ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/
ln -s /usr/share/clickhouse-test/config/text_log.xml /etc/clickhouse-server/config.d/
echo "TSAN_OPTIONS='halt_on_error=1 history_size=7 ignore_noninstrumented_modules=1 verbosity=1'" >> /etc/environment
echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment
echo "ASAN_OPTIONS='malloc_context_size=10 verbosity=1 allocator_release_to_os_interval_ms=10000'" >> /etc/environment
start

View File

@ -5,12 +5,5 @@ ENV TZ=Europe/Moscow
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get install gdb
CMD ln -s /usr/lib/llvm-8/bin/llvm-symbolizer /usr/bin/llvm-symbolizer; \
echo "TSAN_OPTIONS='halt_on_error=1 history_size=7'" >> /etc/environment; \
echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment; \
echo "ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \
echo "UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \
echo "TSAN_SYMBOLIZER_PATH=/usr/lib/llvm-8/bin/llvm-symbolizer" >> /etc/environment; \
echo "LLVM_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \
service zookeeper start && sleep 7 && /usr/share/zookeeper/bin/zkCli.sh -server localhost:2181 -create create /clickhouse_test ''; \
CMD service zookeeper start && sleep 7 && /usr/share/zookeeper/bin/zkCli.sh -server localhost:2181 -create create /clickhouse_test ''; \
gdb -q -ex 'set print inferior-events off' -ex 'set confirm off' -ex 'set print thread-events off' -ex run -ex bt -ex quit --args ./unit_tests_dbms | tee test_output/test_result.txt

View File

@ -38,6 +38,7 @@ toc_title: Adopters
| <a href="https://db.com" class="favicon">Deutsche Bank</a> | Finance | BI Analytics | — | — | [Slides in English, October 2019](https://bigdatadays.ru/wp-content/uploads/2019/10/D2-H3-3_Yakunin-Goihburg.pdf) |
| <a href="https://www.diva-e.com" class="favicon">Diva-e</a> | Digital consulting | Main Product | — | — | [Slides in English, September 2019](https://github.com/ClickHouse/clickhouse-presentations/blob/master/meetup29/ClickHouse-MeetUp-Unusual-Applications-sd-2019-09-17.pdf) |
| <a href="https://www.ecwid.com/" class="favicon">Ecwid</a> | E-commerce SaaS | Metrics, Logging | — | — | [Slides in Russian, April 2019](https://nastachku.ru/var/files/1/presentation/backend/2_Backend_6.pdf) |
| <a href="https://www.ebay.com/" class="favicon">eBay</a> | E-commerce | TBA | — | — | [Webinar, Sep 2020](https://altinity.com/webinarspage/2020/09/08/migrating-from-druid-to-next-gen-olap-on-clickhouse-ebays-experience) |
| <a href="https://www.exness.com" class="favicon">Exness</a> | Trading | Metrics, Logging | — | — | [Talk in Russian, May 2019](https://youtu.be/_rpU-TvSfZ8?t=3215) |
| <a href="https://fastnetmon.com/" class="favicon">FastNetMon</a> | DDoS Protection | Main Product | | — | [Official website](https://fastnetmon.com/docs-fnm-advanced/fastnetmon-advanced-traffic-persistency/) |
| <a href="https://www.flipkart.com/" class="favicon">Flipkart</a> | e-Commerce | — | — | — | [Talk in English, July 2020](https://youtu.be/GMiXCMFDMow?t=239) |

View File

@ -13,49 +13,41 @@ With this instruction you can run basic ClickHouse performance test on any serve
4. ssh to the server and download it with wget:
```bash
# For amd64:
wget https://clickhouse-builds.s3.yandex.net/0/00ba767f5d2a929394ea3be193b1f79074a1c4bc/1578163263_binary/clickhouse
wget https://clickhouse-builds.s3.yandex.net/0/e29c4c3cc47ab2a6c4516486c1b77d57e7d42643/clickhouse_build_check/gcc-10_relwithdebuginfo_none_bundled_unsplitted_disable_False_binary/clickhouse
# For aarch64:
wget https://clickhouse-builds.s3.yandex.net/0/00ba767f5d2a929394ea3be193b1f79074a1c4bc/1578161264_binary/clickhouse
wget https://clickhouse-builds.s3.yandex.net/0/e29c4c3cc47ab2a6c4516486c1b77d57e7d42643/clickhouse_special_build_check/clang-10-aarch64_relwithdebuginfo_none_bundled_unsplitted_disable_False_binary/clickhouse
# Then do:
chmod a+x clickhouse
```
5. Download configs:
```bash
wget https://raw.githubusercontent.com/ClickHouse/ClickHouse/master/programs/server/config.xml
wget https://raw.githubusercontent.com/ClickHouse/ClickHouse/master/programs/server/users.xml
mkdir config.d
wget https://raw.githubusercontent.com/ClickHouse/ClickHouse/master/programs/server/config.d/path.xml -O config.d/path.xml
wget https://raw.githubusercontent.com/ClickHouse/ClickHouse/master/programs/server/config.d/log_to_console.xml -O config.d/log_to_console.xml
```
6. Download benchmark files:
5. Download benchmark files:
```bash
wget https://raw.githubusercontent.com/ClickHouse/ClickHouse/master/benchmark/clickhouse/benchmark-new.sh
chmod a+x benchmark-new.sh
wget https://raw.githubusercontent.com/ClickHouse/ClickHouse/master/benchmark/clickhouse/queries.sql
```
7. Download test data according to the [Yandex.Metrica dataset](../getting-started/example-datasets/metrica.md) instruction (“hits” table containing 100 million rows).
6. Download test data according to the [Yandex.Metrica dataset](../getting-started/example-datasets/metrica.md) instruction (“hits” table containing 100 million rows).
```bash
wget https://clickhouse-datasets.s3.yandex.net/hits/partitions/hits_100m_obfuscated_v1.tar.xz
tar xvf hits_100m_obfuscated_v1.tar.xz -C .
mv hits_100m_obfuscated_v1/* .
```
8. Run the server:
7. Run the server:
```bash
./clickhouse server
```
9. Check the data: ssh to the server in another terminal
8. Check the data: ssh to the server in another terminal
```bash
./clickhouse client --query "SELECT count() FROM hits_100m_obfuscated"
100000000
```
10. Edit the benchmark-new.sh, change `clickhouse-client` to `./clickhouse client` and add `--max_memory_usage 100000000000` parameter.
9. Edit the benchmark-new.sh, change `clickhouse-client` to `./clickhouse client` and add `--max_memory_usage 100000000000` parameter.
```bash
mcedit benchmark-new.sh
```
11. Run the benchmark:
10. Run the benchmark:
```bash
./benchmark-new.sh hits_100m_obfuscated
```
12. Send the numbers and the info about your hardware configuration to clickhouse-feedback@yandex-team.com
11. Send the numbers and the info about your hardware configuration to clickhouse-feedback@yandex-team.com
All the results are published here: https://clickhouse.tech/benchmark/hardware/

View File

@ -563,7 +563,7 @@ ALTER TABLE example_table
- `volume_name_N` — название тома. Названия томов должны быть уникальны.
- `disk` — диск, находящийся внутри тома.
- `max_data_part_size_bytes` — максимальный размер куска данных, который может находится на любом из дисков этого тома.
- `move_factor` — доля свободного места, при превышении которого данные начинают перемещаться на следующий том, если он есть (по умолчанию 0.1).
- `move_factor` — доля доступного свободного места на томе, если места становится меньше, то данные начнут перемещение на следующий том, если он есть (по умолчанию 0.1).
Примеры конфигураций:

View File

@ -9,7 +9,7 @@
- `volume_priority` ([UInt64](../../sql-reference/data-types/int-uint.md)) — порядковый номер тома согласно конфигурации.
- `disks` ([Array(String)](../../sql-reference/data-types/array.md)) — имена дисков, содержащихся в политике хранения.
- `max_data_part_size` ([UInt64](../../sql-reference/data-types/int-uint.md)) — максимальный размер куска данных, который может храниться на дисках тома (0 — без ограничений).
- `move_factor` ([Float64](../../sql-reference/data-types/float.md))\` — доля свободного места, при превышении которой данные начинают перемещаться на следующий том.
- `move_factor` — доля доступного свободного места на томе, если места становится меньше, то данные начнут перемещение на следующий том, если он есть (по умолчанию 0.1).
Если политика хранения содержит несколько томов, то каждому тому соответствует отдельная запись в таблице.

View File

@ -18,7 +18,7 @@ Markdown==3.2.1
MarkupSafe==1.1.1
mkdocs==1.1.2
mkdocs-htmlproofer-plugin==0.0.3
mkdocs-macros-plugin==0.4.9
mkdocs-macros-plugin==0.4.13
nltk==3.5
nose==1.3.7
protobuf==3.13.0

View File

@ -106,7 +106,7 @@ elif [[ $BUILD_TYPE == 'debug' ]]; then
VERSION_POSTFIX+="+debug"
fi
CMAKE_FLAGS=" $MALLOC_OPTS -DSANITIZE=$SANITIZER $CMAKE_FLAGS"
CMAKE_FLAGS=" $MALLOC_OPTS -DSANITIZE=$SANITIZER -DENABLE_CHECK_HEAVY_BUILDS=1 $CMAKE_FLAGS"
[[ -n "$CMAKE_BUILD_TYPE" ]] && CMAKE_FLAGS=" -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE $CMAKE_FLAGS"
export CMAKE_FLAGS

View File

@ -233,6 +233,7 @@ void ThreadPoolImpl<Thread>::worker(typename std::list<Thread>::iterator thread_
std::is_same_v<Thread, std::thread> ? CurrentMetrics::GlobalThreadActive : CurrentMetrics::LocalThreadActive);
job();
job = {};
}
catch (...)
{

View File

@ -48,8 +48,10 @@ static bool supportsRenameat2Impl()
#if defined(__NR_renameat2)
static void renameat2(const std::string & old_path, const std::string & new_path, int flags)
static bool renameat2(const std::string & old_path, const std::string & new_path, int flags)
{
if (!supportsRenameat2())
return false;
if (old_path.empty() || new_path.empty())
throw Exception("Cannot rename " + old_path + " to " + new_path + ": path is empty", ErrorCodes::LOGICAL_ERROR);
@ -57,7 +59,14 @@ static void renameat2(const std::string & old_path, const std::string & new_path
/// int newdirfd (ignored for absolute newpath), const char *newpath,
/// unsigned int flags
if (0 == syscall(__NR_renameat2, AT_FDCWD, old_path.c_str(), AT_FDCWD, new_path.c_str(), flags))
return;
return true;
/// EINVAL means that filesystem does not support one of the flags.
/// It also may happen when running clickhouse in docker with Mac OS as a host OS.
/// supportsRenameat2() with uname is not enough in this case, because virtualized Linux kernel is used.
/// Other cases when EINVAL can be returned should never happen.
if (errno == EINVAL)
return false;
if (errno == EEXIST)
throwFromErrno("Cannot rename " + old_path + " to " + new_path + " because the second path already exists", ErrorCodes::ATOMIC_RENAME_FAIL);
@ -70,10 +79,9 @@ static void renameat2(const std::string & old_path, const std::string & new_path
#define RENAME_NOREPLACE -1
#define RENAME_EXCHANGE -1
[[noreturn]]
static void renameat2(const std::string &, const std::string &, int)
static bool renameat2(const std::string &, const std::string &, int)
{
throw Exception("Compiled without renameat2() support", ErrorCodes::UNSUPPORTED_METHOD);
return false;
}
#endif
@ -104,18 +112,19 @@ bool supportsRenameat2()
void renameNoReplace(const std::string & old_path, const std::string & new_path)
{
if (supportsRenameat2())
renameat2(old_path, new_path, RENAME_NOREPLACE);
else
if (!renameat2(old_path, new_path, RENAME_NOREPLACE))
renameNoReplaceFallback(old_path, new_path);
}
void renameExchange(const std::string & old_path, const std::string & new_path)
{
if (supportsRenameat2())
renameat2(old_path, new_path, RENAME_EXCHANGE);
else
if (!renameat2(old_path, new_path, RENAME_EXCHANGE))
renameExchangeFallback(old_path, new_path);
}
bool renameExchangeIfSupported(const std::string & old_path, const std::string & new_path)
{
return renameat2(old_path, new_path, RENAME_EXCHANGE);
}
}

View File

@ -14,4 +14,7 @@ void renameNoReplace(const std::string & old_path, const std::string & new_path)
/// Atomically exchange oldpath and newpath. Throw exception if some of them does not exist
void renameExchange(const std::string & old_path, const std::string & new_path);
/// Returns false instead of throwing exception if renameat2 is not supported
bool renameExchangeIfSupported(const std::string & old_path, const std::string & new_path);
}

View File

@ -277,7 +277,7 @@ void DatabaseAtomic::commitCreateTable(const ASTCreateQuery & query, const Stora
void DatabaseAtomic::commitAlterTable(const StorageID & table_id, const String & table_metadata_tmp_path, const String & table_metadata_path)
{
bool check_file_exists = supportsRenameat2();
bool check_file_exists = true;
SCOPE_EXIT({ std::error_code code; if (check_file_exists) std::filesystem::remove(table_metadata_tmp_path, code); });
std::unique_lock lock{mutex};
@ -286,9 +286,8 @@ void DatabaseAtomic::commitAlterTable(const StorageID & table_id, const String &
if (table_id.uuid != actual_table_id.uuid)
throw Exception("Cannot alter table because it was renamed", ErrorCodes::CANNOT_ASSIGN_ALTER);
if (check_file_exists)
renameExchange(table_metadata_tmp_path, table_metadata_path);
else
check_file_exists = renameExchangeIfSupported(table_metadata_tmp_path, table_metadata_path);
if (!check_file_exists)
std::filesystem::rename(table_metadata_tmp_path, table_metadata_path);
}

View File

@ -75,7 +75,7 @@ ASTPtr DatabaseMemory::getCreateTableQueryImpl(const String & table_name, const
else
return {};
}
return it->second;
return it->second->clone();
}
UUID DatabaseMemory::tryGetTableUUID(const String & table_name) const

View File

@ -822,7 +822,24 @@ void CacheDictionary::waitForCurrentUpdateFinish(UpdateUnitPtr & update_unit_ptr
if (update_unit_ptr->current_exception)
std::rethrow_exception(update_unit_ptr->current_exception);
{
// There might have been a single update unit for multiple callers in
// independent threads, and current_exception will be the same for them.
// Don't just rethrow it, because sharing the same exception object
// between multiple threads can lead to weird effects if they decide to
// modify it, for example, by adding some error context.
try
{
std::rethrow_exception(update_unit_ptr->current_exception);
}
catch (...)
{
throw DB::Exception(ErrorCodes::CACHE_DICTIONARY_UPDATE_FAIL,
"Dictionary update failed: {}",
getCurrentExceptionMessage(true /*with stack trace*/,
true /*check embedded stack trace*/));
}
}
}
void CacheDictionary::tryPushToUpdateQueueOrThrow(UpdateUnitPtr & update_unit_ptr) const

View File

@ -19,12 +19,8 @@ struct ConstSource;
using NumericArraySources = typename TypeListMap<NumericArraySource, TypeListNumbersAndUInt128>::Type;
using BasicArraySources = typename AppendToTypeList<GenericArraySource, NumericArraySources>::Type;
using NullableArraySources = typename TypeListMap<NullableArraySource, BasicArraySources>::Type;
using BasicAndNullableArraySources = typename TypeListConcat<BasicArraySources, NullableArraySources>::Type;
using ConstArraySources = typename TypeListMap<ConstSource, BasicAndNullableArraySources>::Type;
using TypeListArraySources = typename TypeListConcat<BasicAndNullableArraySources, ConstArraySources>::Type;
class ArraySourceVisitor : public ApplyTypeListForClass<Visitor, TypeListArraySources>::Type
class ArraySourceVisitor : public ApplyTypeListForClass<Visitor, BasicArraySources>::Type
{
protected:
~ArraySourceVisitor() = default;

View File

@ -13,7 +13,6 @@ namespace ErrorCodes
namespace GatherUtils
{
#pragma GCC visibility push(hidden)
struct IArraySink
{
@ -25,6 +24,8 @@ struct IArraySink
}
};
#pragma GCC visibility push(hidden)
template <typename Derived>
class ArraySinkImpl : public Visitable<Derived, IArraySink, ArraySinkVisitor> {};

View File

@ -13,7 +13,6 @@ namespace ErrorCodes
namespace GatherUtils
{
#pragma GCC visibility push(hidden)
struct IArraySource
{
@ -31,6 +30,8 @@ struct IArraySource
}
};
#pragma GCC visibility push(hidden)
template <typename Derived>
class ArraySourceImpl : public Visitable<Derived, IArraySource, ArraySourceVisitor> {};

View File

@ -13,7 +13,6 @@ namespace ErrorCodes
namespace GatherUtils
{
#pragma GCC visibility push(hidden)
struct IValueSource
{
@ -27,6 +26,8 @@ struct IValueSource
virtual bool isConst() const { return false; }
};
#pragma GCC visibility push(hidden)
template <typename Derived>
class ValueSourceImpl : public Visitable<Derived, IValueSource, ValueSourceVisitor> {};

View File

@ -32,20 +32,30 @@ void callSelectMemberFunctionWithTupleArgument(Tuple & tuple, Args && ... args)
callSelectMemberFunctionWithTupleArgument<Base, Tuple, index + 1>(tuple, args ..., std::get<index>(tuple));
}
template <typename Base, typename Tuple, int index, typename ... Args>
void callSelectSource(bool is_const, bool is_nullable, Tuple & tuple, Args && ... args)
{
if constexpr (index == std::tuple_size<Tuple>::value)
Base::selectSource(is_const, is_nullable, args ...);
else
callSelectSource<Base, Tuple, index + 1>(is_const, is_nullable, tuple, args ..., std::get<index>(tuple));
}
template <typename Base, typename ... Args>
struct ArraySourceSelectorVisitor final : public ArraySourceVisitorImpl<ArraySourceSelectorVisitor<Base, Args ...>>
{
explicit ArraySourceSelectorVisitor(Args && ... args) : packed_args(args ...) {}
explicit ArraySourceSelectorVisitor(IArraySource & source, Args && ... args) : packed_args(args ...), array_source(source) {}
using Tuple = std::tuple<Args && ...>;
template <typename Source>
void visitImpl(Source & source)
{
callSelectMemberFunctionWithTupleArgument<Base, Tuple, 0>(packed_args, source);
callSelectSource<Base, Tuple, 0>(array_source.isConst(), array_source.isNullable(), packed_args, source);
}
Tuple packed_args;
IArraySource & array_source;
};
template <typename Base>
@ -54,7 +64,7 @@ struct ArraySourceSelector
template <typename ... Args>
static void select(IArraySource & source, Args && ... args)
{
ArraySourceSelectorVisitor<Base, Args ...> visitor(args ...);
ArraySourceSelectorVisitor<Base, Args ...> visitor(source, args ...);
source.accept(visitor);
}
};
@ -87,56 +97,6 @@ struct ArraySinkSelector
}
};
template <typename Base, typename ... Args>
struct ValueSourceSelectorVisitor final : public ValueSourceVisitorImpl<ValueSourceSelectorVisitor<Base, Args ...>>
{
explicit ValueSourceSelectorVisitor(Args && ... args) : packed_args(args ...) {}
using Tuple = std::tuple<Args && ...>;
template <typename Source>
void visitImpl(Source & source)
{
callSelectMemberFunctionWithTupleArgument<Base, Tuple, 0>(packed_args, source);
}
Tuple packed_args;
};
template <typename Base>
struct ValueSourceSelector
{
template <typename ... Args>
static void select(IValueSource & source, Args && ... args)
{
ValueSourceSelectorVisitor<Base, Args ...> visitor(args ...);
source.accept(visitor);
}
};
template <typename Base>
struct ArraySinkSourceSelector
{
template <typename ... Args>
static void select(IArraySource & source, IArraySink & sink, Args && ... args)
{
ArraySinkSelector<Base>::select(sink, source, args ...);
}
template <typename Sink, typename ... Args>
static void selectImpl(Sink && sink, IArraySource & source, Args && ... args)
{
ArraySourceSelector<Base>::select(source, sink, args ...);
}
template <typename Source, typename Sink, typename ... Args>
static void selectImpl(Source && source, Sink && sink, Args && ... args)
{
Base::selectSourceSink(source, sink, args ...);
}
};
template <typename Base>
struct ArraySourcePairSelector
{
@ -147,15 +107,17 @@ struct ArraySourcePairSelector
}
template <typename FirstSource, typename ... Args>
static void selectImpl(FirstSource && first, IArraySource & second, Args && ... args)
static void selectSource(bool is_const, bool is_nullable, FirstSource && first, IArraySource & second, Args && ... args)
{
ArraySourceSelector<Base>::select(second, first, args ...);
ArraySourceSelector<Base>::select(second, is_const, is_nullable, first, args ...);
}
template <typename SecondSource, typename FirstSource, typename ... Args>
static void selectImpl(SecondSource && second, FirstSource && first, Args && ... args)
static void selectSource(bool is_second_const, bool is_second_nullable, SecondSource && second,
bool is_first_const, bool is_first_nullable, FirstSource && first, Args && ... args)
{
Base::selectSourcePair(first, second, args ...);
Base::selectSourcePair(is_first_const, is_first_nullable, first,
is_second_const, is_second_nullable, second, args ...);
}
};

View File

@ -24,36 +24,31 @@ struct ArrayConcat : public ArraySourceSelector<ArrayConcat>
using Sources = std::vector<std::unique_ptr<IArraySource>>;
template <typename Source>
static void selectImpl(Source && source, const Sources & sources, ColumnArray::MutablePtr & result)
static void selectSource(bool /*is_const*/, bool is_nullable, Source & source, const Sources & sources, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
concat<SourceType, Sink>(sources, std::move(sink));
}
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
template <typename Source>
static void selectImpl(ConstSource<Source> && source, const Sources & sources, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
auto & nullable_source = static_cast<NullableSource &>(source);
concat<SourceType, Sink>(sources, std::move(sink));
}
template <typename Source>
static void selectImpl(ConstSource<Source> & source, const Sources & sources, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
concat<SourceType, Sink>(sources, std::move(sink));
concat<NullableSource, NullableSink>(sources, std::move(sink));
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
concat<SourceType, Sink>(sources, std::move(sink));
}
}
};

View File

@ -11,9 +11,53 @@ namespace
struct ArrayHasAllSelectArraySourcePair : public ArraySourcePairSelector<ArrayHasAllSelectArraySourcePair>
{
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(FirstSource && first, SecondSource && second, ColumnUInt8 & result)
static void callFunction(FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
arrayAllAny<ArraySearchType::All>(first, second, result);
using SourceType = typename std::decay<SecondSource>::type;
if (is_second_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_second_const)
arrayAllAny<ArraySearchType::All>(first, static_cast<ConstSource<NullableSource> &>(second), result);
else
arrayAllAny<ArraySearchType::All>(first, static_cast<NullableSource &>(second), result);
}
else
{
if (is_second_const)
arrayAllAny<ArraySearchType::All>(first, static_cast<ConstSource<SourceType> &>(second), result);
else
arrayAllAny<ArraySearchType::All>(first, second, result);
}
}
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(bool is_first_const, bool is_first_nullable, FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
using SourceType = typename std::decay<FirstSource>::type;
if (is_first_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_first_const)
callFunction(static_cast<ConstSource<NullableSource> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(static_cast<NullableSource &>(first), is_second_const, is_second_nullable, second, result);
}
else
{
if (is_first_const)
callFunction(static_cast<ConstSource<SourceType> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(first, is_second_const, is_second_nullable, second, result);
}
}
};

View File

@ -11,9 +11,53 @@ namespace
struct ArrayHasAnySelectArraySourcePair : public ArraySourcePairSelector<ArrayHasAnySelectArraySourcePair>
{
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(FirstSource && first, SecondSource && second, ColumnUInt8 & result)
static void callFunction(FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
arrayAllAny<ArraySearchType::Any>(first, second, result);
using SourceType = typename std::decay<SecondSource>::type;
if (is_second_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_second_const)
arrayAllAny<ArraySearchType::Any>(first, static_cast<ConstSource<NullableSource> &>(second), result);
else
arrayAllAny<ArraySearchType::Any>(first, static_cast<NullableSource &>(second), result);
}
else
{
if (is_second_const)
arrayAllAny<ArraySearchType::Any>(first, static_cast<ConstSource<SourceType> &>(second), result);
else
arrayAllAny<ArraySearchType::Any>(first, second, result);
}
}
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(bool is_first_const, bool is_first_nullable, FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
using SourceType = typename std::decay<FirstSource>::type;
if (is_first_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_first_const)
callFunction(static_cast<ConstSource<NullableSource> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(static_cast<NullableSource &>(first), is_second_const, is_second_nullable, second, result);
}
else
{
if (is_first_const)
callFunction(static_cast<ConstSource<SourceType> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(first, is_second_const, is_second_nullable, second, result);
}
}
};

View File

@ -11,9 +11,53 @@ namespace
struct ArrayHasSubstrSelectArraySourcePair : public ArraySourcePairSelector<ArrayHasSubstrSelectArraySourcePair>
{
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(FirstSource && first, SecondSource && second, ColumnUInt8 & result)
static void callFunction(FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
arrayAllAny<ArraySearchType::Substr>(first, second, result);
using SourceType = typename std::decay<SecondSource>::type;
if (is_second_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_second_const)
arrayAllAny<ArraySearchType::Substr>(first, static_cast<ConstSource<NullableSource> &>(second), result);
else
arrayAllAny<ArraySearchType::Substr>(first, static_cast<NullableSource &>(second), result);
}
else
{
if (is_second_const)
arrayAllAny<ArraySearchType::Substr>(first, static_cast<ConstSource<SourceType> &>(second), result);
else
arrayAllAny<ArraySearchType::Substr>(first, second, result);
}
}
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(bool is_first_const, bool is_first_nullable, FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
using SourceType = typename std::decay<FirstSource>::type;
if (is_first_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_first_const)
callFunction(static_cast<ConstSource<NullableSource> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(static_cast<NullableSource &>(first), is_second_const, is_second_nullable, second, result);
}
else
{
if (is_first_const)
callFunction(static_cast<ConstSource<SourceType> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(first, is_second_const, is_second_nullable, second, result);
}
}
};

View File

@ -13,13 +13,37 @@ namespace
struct SliceDynamicOffsetBoundedSelectArraySource : public ArraySourceSelector<SliceDynamicOffsetBoundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, const IColumn & offset_column, const IColumn & length_column, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source,
const IColumn & offset_column, const IColumn & length_column, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceDynamicOffsetBounded(source, sink, offset_column, length_column);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetBounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset_column, length_column);
else
sliceDynamicOffsetBounded(static_cast<NullableSource &>(source), sink, offset_column, length_column);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetBounded(static_cast<ConstSource<SourceType> &>(source), sink, offset_column, length_column);
else
sliceDynamicOffsetBounded(source, sink, offset_column, length_column);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceDynamicOffsetUnboundedSelectArraySource
: public ArraySourceSelector<SliceDynamicOffsetUnboundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, const IColumn & offset_column, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, const IColumn & offset_column, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceDynamicOffsetUnbounded(source, sink, offset_column);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetUnbounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset_column);
else
sliceDynamicOffsetUnbounded(static_cast<NullableSource &>(source), sink, offset_column);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetUnbounded(static_cast<ConstSource<SourceType> &>(source), sink, offset_column);
else
sliceDynamicOffsetUnbounded(source, sink, offset_column);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromLeftConstantOffsetBoundedSelectArraySource
: public ArraySourceSelector<SliceFromLeftConstantOffsetBoundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromLeftConstantOffsetBounded(source, sink, offset, length);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetBounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset, length);
else
sliceFromLeftConstantOffsetBounded(static_cast<NullableSource &>(source), sink, offset, length);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetBounded(static_cast<ConstSource<SourceType> &>(source), sink, offset, length);
else
sliceFromLeftConstantOffsetBounded(source, sink, offset, length);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromLeftConstantOffsetUnboundedSelectArraySource
: public ArraySourceSelector<SliceFromLeftConstantOffsetUnboundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromLeftConstantOffsetUnbounded(source, sink, offset);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetUnbounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset);
else
sliceFromLeftConstantOffsetUnbounded(static_cast<NullableSource &>(source), sink, offset);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetUnbounded(static_cast<ConstSource<SourceType> &>(source), sink, offset);
else
sliceFromLeftConstantOffsetUnbounded(source, sink, offset);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromRightConstantOffsetBoundedSelectArraySource
: public ArraySourceSelector<SliceFromRightConstantOffsetBoundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromRightConstantOffsetBounded(source, sink, offset, length);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetBounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset, length);
else
sliceFromRightConstantOffsetBounded(static_cast<NullableSource &>(source), sink, offset, length);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetBounded(static_cast<ConstSource<SourceType> &>(source), sink, offset, length);
else
sliceFromRightConstantOffsetBounded(source, sink, offset, length);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromRightConstantOffsetUnboundedSelectArraySource
: public ArraySourceSelector<SliceFromRightConstantOffsetUnboundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromRightConstantOffsetUnbounded(source, sink, offset);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetUnbounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset);
else
sliceFromRightConstantOffsetUnbounded(static_cast<NullableSource &>(source), sink, offset);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetUnbounded(static_cast<ConstSource<SourceType> &>(source), sink, offset);
else
sliceFromRightConstantOffsetUnbounded(source, sink, offset);
}
}
};

View File

@ -607,8 +607,16 @@ void ExpressionActions::execute(Block & block, bool dry_run) const
{
for (const auto & action : actions)
{
action.execute(block, dry_run);
checkLimits(block);
try
{
action.execute(block, dry_run);
checkLimits(block);
}
catch (Exception & e)
{
e.addMessage(fmt::format("while executing '{}'", action.toString()));
throw;
}
}
}

View File

@ -12,3 +12,21 @@
4 5
4 5
4 5
---------------------------
42
42
0
42
42
42
\N
42
42
42
42
42
45
\N
\N
42
42

View File

@ -11,3 +11,63 @@ SELECT * FROM (WITH test1 AS (SELECT toInt32(*) i FROM numbers(5)) SELECT * FROM
WITH test1 AS (SELECT i + 1, j + 1 FROM test1) SELECT toInt64(4) i, toInt64(5) j FROM numbers(3) WHERE (i, j) IN test1;
DROP TABLE IF EXISTS test1;
select '---------------------------';
set empty_result_for_aggregation_by_empty_set = 0;
WITH test1 AS (SELECT number-1 as n FROM numbers(42))
SELECT max(n+1)+1 z FROM test1;
WITH test1 AS (SELECT number-1 as n FROM numbers(42))
SELECT max(n+1)+1 z FROM test1 join test1 x using n having z - 1 = (select min(n-1)+41 from test1) + 2;
WITH test1 AS (SELECT number-1 as n FROM numbers(4442) order by n limit 100)
SELECT max(n) FROM test1 where n=422;
WITH test1 AS (SELECT number-1 as n FROM numbers(4442) order by n limit 100)
SELECT max(n) FROM test1 where n=42;
drop table if exists with_test ;
create table with_test engine=Memory as select cast(number-1 as Nullable(Int64)) n from numbers(10000);
WITH test1 AS (SELECT n FROM with_test where n <= 40)
SELECT max(n+1)+1 z FROM test1 join test1 x using (n) having max(n+1)+1 - 1 = (select min(n-1)+41 from test1) + 2;
WITH test1 AS (SELECT n FROM with_test where n <= 40)
SELECT max(n+1)+1 z FROM test1 join test1 x using (n) having z - 1 = (select min(n-1)+41 from test1) + 2;
WITH test1 AS (SELECT n FROM with_test order by n limit 100)
SELECT max(n) FROM test1 where n=422;
WITH test1 AS (SELECT n FROM with_test order by n limit 100)
SELECT max(n) FROM test1 where n=42;
WITH test1 AS (SELECT n FROM with_test where n = 42 order by n limit 100)
SELECT max(n) FROM test1 where n=42;
WITH test1 AS (SELECT n FROM with_test where n = 42 or 1=1 order by n limit 100)
SELECT max(n) FROM test1 where n=42;
WITH test1 AS (SELECT n, null as b FROM with_test where n = 42 or b is null order by n limit 100)
SELECT max(n) FROM test1 where n=42;
WITH test1 AS (SELECT n, null b FROM with_test where b is null)
SELECT max(n) FROM test1 where n=42;
WITH test1 AS (SELECT n, null b FROM with_test where b is null or 1=1)
SELECT max(n) FROM test1 where n=45;
WITH test1 AS (SELECT n, null b FROM with_test where b is null and n = 42)
SELECT max(n) FROM test1 where n=45;
WITH test1 AS (SELECT n, null b FROM with_test where 1=1 and n = 42 order by n)
SELECT max(n) FROM test1 where n=45;
WITH test1 AS (SELECT n, null b, n+1 m FROM with_test where 1=0 or n = 42 order by n limit 4)
SELECT max(n) m FROM test1 where test1.m=43 having max(n)=42;
WITH test1 AS (SELECT n, null b, n+1 m FROM with_test where n = 42 order by n limit 4)
SELECT max(n) m FROM test1 where b is null and test1.m=43 having m=42 limit 4;
drop table with_test ;

View File

@ -0,0 +1,2 @@
[0,1,2,3,4,5,6,7,8,9]
['0','1','2','3','4','5','6','7','8','9']

View File

@ -0,0 +1,11 @@
DROP TABLE IF EXISTS testv;
create view testv(a UInt32) as select number a from numbers(10);
select groupArray(a) from testv;
DROP TABLE testv;
create view testv(a String) as select number a from numbers(10);
select groupArray(a) from testv;
DROP TABLE testv;

View File

@ -0,0 +1,21 @@
abc
def
ghi
---
abc
def
xyz
---
abc
def
xyz
abc
def
xyz
---
abc
def
xyz
abc
def
xyz

View File

@ -0,0 +1,23 @@
DROP TABLE IF EXISTS t;
DROP TABLE IF EXISTS d;
CREATE TABLE t (x Enum8('abc' = 0, 'def' = 1, 'ghi' = 2)) ENGINE = TinyLog;
INSERT INTO t VALUES (0), (1), (2);
SELECT * FROM t;
SELECT '---';
CREATE TABLE d (x Enum8('abc' = 0, 'def' = 1, 'xyz' = 2)) ENGINE = Distributed(test_shard_localhost, currentDatabase(), t);
SELECT * FROM d;
DROP TABLE d;
SELECT '---';
CREATE TABLE d (x Enum8('abc' = 0, 'def' = 1, 'xyz' = 2)) ENGINE = Distributed(test_cluster_two_shards, currentDatabase(), t);
SELECT * FROM d;
DROP TABLE d;
SELECT '---';
CREATE TABLE d (x Enum8('abc' = 0, 'def' = 1, 'xyz' = 2)) ENGINE = Distributed(test_cluster_two_shards_localhost, currentDatabase(), t);
SELECT * FROM d;
DROP TABLE d;
DROP TABLE t;

View File

@ -144,3 +144,4 @@
01473_event_time_microseconds
01461_query_start_time_microseconds
01455_shard_leaf_max_rows_bytes_to_read
01505_distributed_local_type_conversion_enum

View File

@ -68,7 +68,8 @@ Results for Yandex Managed ClickHouse for "cold cache" are biased and should not
Results for AWS Lightsail is from <b>Vamsi Krishna B.</b><br/>
Results for Dell XPS laptop and Google Pixel phone is from <b>Alexander Kuzmenkov</b>.<br/>
Results for Android phones for "cold cache" are done without cache flushing, so they are not "cold" and cannot be compared.<br/>
Results for Digital Ocean are from <b>Zimin Aleksey</b>.
Results for Digital Ocean are from <b>Zimin Aleksey</b>.<br/>
Results for 2x EPYC 7642 w/ 512 GB RAM (192 Cores) + 12X 1TB SSD (RAID6) are from <b>Yiğit Konur</b> and <b>Metehan Çetinkaya</b> of seo.do.
</p>
</div>
</div>

View File

@ -0,0 +1,56 @@
[
{
"system": "AMD EPYC 7642",
"system_full": "2x AMD EPYC 7642 / 512 GB RAM / 12x 1TB SSD (RAID 6)",
"time": "2020-09-21 00:00:00",
"kind": "server",
"result":
[
[0.003, 0.003, 0.002],
[0.039, 0.041, 0.024],
[0.052, 0.029, 0.029],
[0.087, 0.031, 0.032],
[0.152, 0.106, 0.105],
[0.204, 0.128, 0.128],
[0.049, 0.028, 0.027],
[0.031, 0.024, 0.027],
[0.190, 0.130, 0.125],
[0.210, 0.142, 0.138],
[0.142, 0.091, 0.087],
[0.143, 0.101, 0.097],
[0.318, 0.170, 0.163],
[0.303, 0.193, 0.191],
[0.240, 0.175, 0.166],
[0.200, 0.166, 0.161],
[0.466, 0.364, 0.345],
[0.298, 0.244, 0.231],
[1.288, 0.901, 0.859],
[0.087, 0.031, 0.025],
[0.663, 0.201, 0.191],
[0.661, 0.213, 0.154],
[1.118, 0.599, 0.593],
[1.708, 0.392, 0.318],
[0.202, 0.065, 0.066],
[0.135, 0.061, 0.057],
[0.203, 0.066, 0.067],
[0.630, 0.296, 0.290],
[0.578, 0.281, 0.262],
[0.662, 0.670, 0.639],
[0.241, 0.153, 0.150],
[0.424, 0.235, 0.231],
[1.505, 1.090, 1.090],
[1.038, 0.818, 0.799],
[1.064, 0.856, 0.809],
[0.332, 0.297, 0.275],
[0.200, 0.169, 0.168],
[0.083, 0.070, 0.071],
[0.090, 0.059, 0.063],
[0.416, 0.419, 0.398],
[0.048, 0.032, 0.032],
[0.036, 0.027, 0.025],
[0.007, 0.007, 0.007]
]
}
]