mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 08:40:50 +00:00
Merge branch 'master' into codecs_for_nested_types
This commit is contained in:
commit
b57708c3dd
@ -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
120
benchmark/hardware.sh
Executable 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
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
|
@ -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 \
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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):
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) |
|
||||
|
@ -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/
|
||||
|
@ -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).
|
||||
|
||||
Примеры конфигураций:
|
||||
|
||||
|
@ -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).
|
||||
|
||||
Если политика хранения содержит несколько томов, то каждому тому соответствует отдельная запись в таблице.
|
||||
|
||||
|
@ -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
|
||||
|
2
release
2
release
@ -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
|
||||
|
@ -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 (...)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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> {};
|
||||
|
||||
|
@ -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> {};
|
||||
|
||||
|
@ -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> {};
|
||||
|
||||
|
@ -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 ...);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ;
|
||||
|
@ -0,0 +1,2 @@
|
||||
[0,1,2,3,4,5,6,7,8,9]
|
||||
['0','1','2','3','4','5','6','7','8','9']
|
11
tests/queries/0_stateless/01504_view_type_conversion.sql
Normal file
11
tests/queries/0_stateless/01504_view_type_conversion.sql
Normal 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;
|
@ -0,0 +1,21 @@
|
||||
abc
|
||||
def
|
||||
ghi
|
||||
---
|
||||
abc
|
||||
def
|
||||
xyz
|
||||
---
|
||||
abc
|
||||
def
|
||||
xyz
|
||||
abc
|
||||
def
|
||||
xyz
|
||||
---
|
||||
abc
|
||||
def
|
||||
xyz
|
||||
abc
|
||||
def
|
||||
xyz
|
@ -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;
|
@ -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
|
||||
|
@ -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>
|
||||
|
56
website/benchmark/hardware/results/052_amd_epyc_7642.json
Normal file
56
website/benchmark/hardware/results/052_amd_epyc_7642.json
Normal 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]
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user