Migrate documentation to AsciiDoc
This commit sets up a new documentation structure and format:
* The directory struture changes from a Sphinx project to an Antora module layout.
* The formatting of the content changes from reStructuredText to AsciiDoc.
The documentation must now be built and published with Antora. Initially only from the cassandra-website repository.
This change was done to make maintaining versioned website documentation easier. As Antora is designed to generate versioned documentation.
The old directory structure was:
<ROOT>
- doc/
- cql3/
- CQL.css
- CQL.textile
- source/
- _static/
- _templates/
- _theme/
- _util/
- <other directory sections>/
- conf.py
- index.rst
- <other *.rst pages>
- make.bat
- Makefile
- README.md
- SASI.md
- <*.spec files>
- <generation scripts>
The new directory structure organises the documentation into modules:
<ROOT>
- doc/
- cql3
- modules/
- cassandra/
- assets/
- examples/
- pages/
- partials/
- nav.adoc
- ROOT/
- pages/
- nav.adoc
- scripts/
- antora.yaml
- README.md
- SASI.md
patch by Lorina Poland, Anthony Grasso; reviewed by Anthony Grasso, Mick Semb Wever for CASSANDRA-16763
Co-authored-by: Anthony Grasso <anthony@thelastpickle.com>
|
|
@ -53,6 +53,7 @@
|
|||
<exclude name="**/cassandra.yaml"/>
|
||||
<exclude name="**/cassandra-murmur.yaml"/>
|
||||
<exclude name="**/cassandra-seeds.yaml"/>
|
||||
<exclude NAME="**/doc/antora.yml"/>
|
||||
<exclude name="**/test/conf/cassandra.yaml"/>
|
||||
<exclude name="**/test/conf/cassandra_encryption.yaml"/>
|
||||
<exclude name="**/test/conf/cdc.yaml"/>
|
||||
|
|
@ -67,6 +68,8 @@
|
|||
<exclude name="**/tools/cqlstress-example.yaml"/>
|
||||
<exclude name="**/tools/cqlstress-insanity-example.yaml"/>
|
||||
<exclude name="**/tools/cqlstress-lwt-example.yaml"/>
|
||||
<!-- Documentation files -->
|
||||
<exclude NAME="**/doc/modules/**/*"/>
|
||||
<!-- NOTICE files -->
|
||||
<exclude NAME="**/NOTICE.md"/>
|
||||
<!-- LICENSE files -->
|
||||
|
|
|
|||
|
|
@ -68,7 +68,9 @@ Thumbs.db
|
|||
.ant_targets
|
||||
|
||||
# Generated files from the documentation
|
||||
doc/source/configuration/cassandra_config_file.rst
|
||||
doc/modules/cassandra/pages/configuration/cass_yaml_file.adoc
|
||||
doc/modules/cassandra/pages/tools/nodetool/
|
||||
doc/modules/cassandra/examples/TEXT/NODETOOL/
|
||||
|
||||
# Python virtual environment
|
||||
venv/
|
||||
|
|
|
|||
11
build.xml
|
|
@ -254,13 +254,14 @@
|
|||
</wikitext-to-html>
|
||||
</target>
|
||||
|
||||
<target name="gen-doc" description="Generate documentation" depends="jar" unless="ant.gen-doc.skip">
|
||||
<target name="gen-asciidoc" description="Generate dynamic asciidoc pages" depends="jar" unless="ant.gen-doc.skip">
|
||||
<exec executable="make" osfamily="unix" dir="${doc.dir}">
|
||||
<arg value="html"/>
|
||||
<arg value="gen-asciidoc"/>
|
||||
</exec>
|
||||
<exec executable="cmd" osfamily="dos" dir="${doc.dir}">
|
||||
<arg value="/c"/>
|
||||
<arg value="make.bat"/>
|
||||
</target>
|
||||
|
||||
<target name="gen-doc" description="Generate documentation" depends="gen-asciidoc,generate-cql-html" unless="ant.gen-doc.skip">
|
||||
<exec executable="make" osfamily="unix" dir="${doc.dir}">
|
||||
<arg value="html"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
|
|
|||
284
doc/Makefile
|
|
@ -1,268 +1,26 @@
|
|||
# Makefile for Sphinx documentation
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
|
||||
YAML_DOC_INPUT=../conf/cassandra.yaml
|
||||
YAML_DOC_OUTPUT=source/configuration/cassandra_config_file.rst
|
||||
|
||||
MAKE_CASSANDRA_YAML = python convert_yaml_to_rst.py $(YAML_DOC_INPUT) $(YAML_DOC_OUTPUT)
|
||||
|
||||
WEB_SITE_PRESENCE_FILE='source/.build_for_website'
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " website to make HTML files for the Cassandra website"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " applehelp to make an Apple Help Book"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " epub3 to make an epub3"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
@echo " coverage to run coverage check of the documentation (if enabled)"
|
||||
@echo " dummy to check syntax errors of document sources"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
rm -f $(YAML_DOC_OUTPUT)
|
||||
GENERATE_NODETOOL_DOCS = ./scripts/gen-nodetool-docs.py
|
||||
MAKE_CASSANDRA_YAML = ./scripts/convert_yaml_to_adoc.py ../conf/cassandra.yaml ./modules/cassandra/pages/configuration/cass_yaml_file.adoc
|
||||
|
||||
.PHONY: html
|
||||
html:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
@# hack until a local basic antora build is put in
|
||||
|
||||
.PHONY: website
|
||||
website: clean
|
||||
@touch $(WEB_SITE_PRESENCE_FILE)
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@rm $(WEB_SITE_PRESENCE_FILE)
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
.PHONY: dirhtml
|
||||
dirhtml:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
.PHONY: singlehtml
|
||||
singlehtml:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
.PHONY: pickle
|
||||
pickle:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
.PHONY: json
|
||||
json:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
.PHONY: htmlhelp
|
||||
htmlhelp:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
.PHONY: qthelp
|
||||
qthelp:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ApacheCassandraDocumentation.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ApacheCassandraDocumentation.qhc"
|
||||
|
||||
.PHONY: applehelp
|
||||
applehelp:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
||||
@echo
|
||||
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
|
||||
@echo "N.B. You won't be able to view it unless you put it in" \
|
||||
"~/Library/Documentation/Help or install it in your application" \
|
||||
"bundle."
|
||||
|
||||
.PHONY: devhelp
|
||||
devhelp:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/ApacheCassandraDocumentation"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ApacheCassandraDocumentation"
|
||||
@echo "# devhelp"
|
||||
|
||||
.PHONY: epub
|
||||
epub:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
.PHONY: epub3
|
||||
epub3:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
|
||||
@echo
|
||||
@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
|
||||
|
||||
.PHONY: latex
|
||||
latex:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
.PHONY: latexpdf
|
||||
latexpdf:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
.PHONY: latexpdfja
|
||||
latexpdfja:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
.PHONY: text
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
.PHONY: man
|
||||
man:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
.PHONY: texinfo
|
||||
texinfo:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
.PHONY: info
|
||||
info:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
.PHONY: gettext
|
||||
gettext:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
.PHONY: changes
|
||||
changes:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
.PHONY: linkcheck
|
||||
linkcheck:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
.PHONY: doctest
|
||||
doctest:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
||||
@echo "Testing of coverage in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/coverage/python.txt."
|
||||
|
||||
.PHONY: xml
|
||||
xml:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
.PHONY: pseudoxml
|
||||
pseudoxml:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||
|
||||
.PHONY: dummy
|
||||
dummy:
|
||||
$(MAKE_CASSANDRA_YAML)
|
||||
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
|
||||
@echo
|
||||
@echo "Build finished. Dummy builder generates no files."
|
||||
.PHONY: gen-asciidoc
|
||||
gen-asciidoc:
|
||||
@mkdir -p modules/cassandra/pages/tools/nodetool
|
||||
@mkdir -p modules/cassandra/examples/TEXT/NODETOOL
|
||||
python3 $(GENERATE_NODETOOL_DOCS)
|
||||
python3 $(MAKE_CASSANDRA_YAML)
|
||||
|
|
|
|||
|
|
@ -23,29 +23,39 @@ Apache Cassandra documentation directory
|
|||
|
||||
This directory contains the documentation maintained in-tree for Apache
|
||||
Cassandra. This directory contains the following documents:
|
||||
- The source of the official Cassandra documentation, in the `source/`
|
||||
- The source of the official Cassandra documentation, in the `source/modules`
|
||||
subdirectory. See below for more details on how to edit/build that
|
||||
documentation.
|
||||
- The specification(s) for the supported versions of native transport protocol.
|
||||
- Additional documentation on the SASI implementation (`SASI.md`). TODO: we
|
||||
should probably move the first half of that documentation to the general
|
||||
documentation, and the implementation explanation parts into the wiki.
|
||||
|
||||
|
||||
Official documentation
|
||||
----------------------
|
||||
|
||||
The source for the official documentation for Apache Cassandra can be found in
|
||||
the `source` subdirectory. The documentation uses [sphinx](http://www.sphinx-doc.org/)
|
||||
and is thus written in [reStructuredText](http://docutils.sourceforge.net/rst.html).
|
||||
the `modules/cassandra/pages` subdirectory. The documentation uses [antora](http://www.antora.org/)
|
||||
and is thus written in [asciidoc](http://asciidoc.org).
|
||||
|
||||
To build the HTML documentation, you will need to first install sphinx and the
|
||||
[sphinx ReadTheDocs theme](the https://pypi.python.org/pypi/sphinx_rtd_theme), which
|
||||
on unix you can do with:
|
||||
To generate the asciidoc files for cassandra.yaml and the nodetool commands, run (from project root):
|
||||
```bash
|
||||
ant gen-asciidoc
|
||||
```
|
||||
pip install sphinx sphinx_rtd_theme
|
||||
or (from this directory):
|
||||
|
||||
```bash
|
||||
make gen-asciidoc
|
||||
```
|
||||
|
||||
|
||||
(The following has not yet been implemented, for now see the build instructions in the [cassandra-website](https://github.com/apache/cassandra-website) repo.)
|
||||
To build the documentation, run (from project root):
|
||||
|
||||
```bash
|
||||
ant gen-doc
|
||||
```
|
||||
or (from this directory):
|
||||
|
||||
```bash
|
||||
make html
|
||||
```
|
||||
|
||||
The documentation can then be built from this directory by calling `make html`
|
||||
(or `make.bat html` on windows). Alternatively, the top-level `ant gen-doc`
|
||||
target can be used.
|
||||
|
|
|
|||
798
doc/SASI.md
|
|
@ -1,798 +0,0 @@
|
|||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
# SASIIndex
|
||||
|
||||
[`SASIIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/SASIIndex.java),
|
||||
or "SASI" for short, is an implementation of Cassandra's
|
||||
`Index` interface that can be used as an alternative to the
|
||||
existing implementations. SASI's indexing and querying improves on
|
||||
existing implementations by tailoring it specifically to Cassandra's
|
||||
needs. SASI has superior performance in cases where queries would
|
||||
previously require filtering. In achieving this performance, SASI aims
|
||||
to be significantly less resource intensive than existing
|
||||
implementations, in memory, disk, and CPU usage. In addition, SASI
|
||||
supports prefix and contains queries on strings (similar to SQL's
|
||||
`LIKE = "foo*"` or `LIKE = "*foo*"'`).
|
||||
|
||||
The following goes on describe how to get up and running with SASI,
|
||||
demonstrates usage with examples, and provides some details on its
|
||||
implementation.
|
||||
|
||||
## Using SASI
|
||||
|
||||
The examples below walk through creating a table and indexes on its
|
||||
columns, and performing queries on some inserted data. The patchset in
|
||||
this repository includes support for the Thrift and CQL3 interfaces.
|
||||
|
||||
The examples below assume the `demo` keyspace has been created and is
|
||||
in use.
|
||||
|
||||
```
|
||||
cqlsh> CREATE KEYSPACE demo WITH replication = {
|
||||
... 'class': 'SimpleStrategy',
|
||||
... 'replication_factor': '1'
|
||||
... };
|
||||
cqlsh> USE demo;
|
||||
```
|
||||
|
||||
All examples are performed on the `sasi` table:
|
||||
|
||||
```
|
||||
cqlsh:demo> CREATE TABLE sasi (id uuid, first_name text, last_name text,
|
||||
... age int, height int, created_at bigint, primary key (id));
|
||||
```
|
||||
|
||||
#### Creating Indexes
|
||||
|
||||
To create SASI indexes use CQLs `CREATE CUSTOM INDEX` statement:
|
||||
|
||||
```
|
||||
cqlsh:demo> CREATE CUSTOM INDEX ON sasi (first_name) USING 'org.apache.cassandra.index.sasi.SASIIndex'
|
||||
... WITH OPTIONS = {
|
||||
... 'analyzer_class':
|
||||
... 'org.apache.cassandra.index.sasi.analyzer.NonTokenizingAnalyzer',
|
||||
... 'case_sensitive': 'false'
|
||||
... };
|
||||
|
||||
cqlsh:demo> CREATE CUSTOM INDEX ON sasi (last_name) USING 'org.apache.cassandra.index.sasi.SASIIndex'
|
||||
... WITH OPTIONS = {'mode': 'CONTAINS'};
|
||||
|
||||
cqlsh:demo> CREATE CUSTOM INDEX ON sasi (age) USING 'org.apache.cassandra.index.sasi.SASIIndex';
|
||||
|
||||
cqlsh:demo> CREATE CUSTOM INDEX ON sasi (created_at) USING 'org.apache.cassandra.index.sasi.SASIIndex'
|
||||
... WITH OPTIONS = {'mode': 'SPARSE'};
|
||||
```
|
||||
|
||||
The indexes created have some options specified that customize their
|
||||
behaviour and potentially performance. The index on `first_name` is
|
||||
case-insensitive. The analyzers are discussed more in a subsequent
|
||||
example. The `NonTokenizingAnalyzer` performs no analysis on the
|
||||
text. Each index has a mode: `PREFIX`, `CONTAINS`, or `SPARSE`, the
|
||||
first being the default. The `last_name` index is created with the
|
||||
mode `CONTAINS` which matches terms on suffixes instead of prefix
|
||||
only. Examples of this are available below and more detail can be
|
||||
found in the section on
|
||||
[OnDiskIndex](#ondiskindexbuilder).The
|
||||
`created_at` column is created with its mode set to `SPARSE`, which is
|
||||
meant to improve performance of querying large, dense number ranges
|
||||
like timestamps for data inserted every millisecond. Details of the
|
||||
`SPARSE` implementation can also be found in the section on the
|
||||
[OnDiskIndex](#ondiskindexbuilder). The `age`
|
||||
index is created with the default `PREFIX` mode and no
|
||||
case-sensitivity or text analysis options are specified since the
|
||||
field is numeric.
|
||||
|
||||
After inserting the following data and performing a `nodetool flush`,
|
||||
SASI performing index flushes to disk can be seen in Cassandra's logs
|
||||
-- although the direct call to flush is not required (see
|
||||
[IndexMemtable](#indexmemtable) for more details).
|
||||
|
||||
```
|
||||
cqlsh:demo> INSERT INTO sasi (id, first_name, last_name, age, height, created_at)
|
||||
... VALUES (556ebd54-cbe5-4b75-9aae-bf2a31a24500, 'Pavel', 'Yaskevich', 27, 181, 1442959315018);
|
||||
|
||||
cqlsh:demo> INSERT INTO sasi (id, first_name, last_name, age, height, created_at)
|
||||
... VALUES (5770382a-c56f-4f3f-b755-450e24d55217, 'Jordan', 'West', 26, 173, 1442959315019);
|
||||
|
||||
cqlsh:demo> INSERT INTO sasi (id, first_name, last_name, age, height, created_at)
|
||||
... VALUES (96053844-45c3-4f15-b1b7-b02c441d3ee1, 'Mikhail', 'Stepura', 36, 173, 1442959315020);
|
||||
|
||||
cqlsh:demo> INSERT INTO sasi (id, first_name, last_name, age, height, created_at)
|
||||
... VALUES (f5dfcabe-de96-4148-9b80-a1c41ed276b4, 'Michael', 'Kjellman', 26, 180, 1442959315021);
|
||||
|
||||
cqlsh:demo> INSERT INTO sasi (id, first_name, last_name, age, height, created_at)
|
||||
... VALUES (2970da43-e070-41a8-8bcb-35df7a0e608a, 'Johnny', 'Zhang', 32, 175, 1442959315022);
|
||||
|
||||
cqlsh:demo> INSERT INTO sasi (id, first_name, last_name, age, height, created_at)
|
||||
... VALUES (6b757016-631d-4fdb-ac62-40b127ccfbc7, 'Jason', 'Brown', 40, 182, 1442959315023);
|
||||
|
||||
cqlsh:demo> INSERT INTO sasi (id, first_name, last_name, age, height, created_at)
|
||||
... VALUES (8f909e8a-008e-49dd-8d43-1b0df348ed44, 'Vijay', 'Parthasarathy', 34, 183, 1442959315024);
|
||||
|
||||
cqlsh:demo> SELECT first_name, last_name, age, height, created_at FROM sasi;
|
||||
|
||||
first_name | last_name | age | height | created_at
|
||||
------------+---------------+-----+--------+---------------
|
||||
Michael | Kjellman | 26 | 180 | 1442959315021
|
||||
Mikhail | Stepura | 36 | 173 | 1442959315020
|
||||
Jason | Brown | 40 | 182 | 1442959315023
|
||||
Pavel | Yaskevich | 27 | 181 | 1442959315018
|
||||
Vijay | Parthasarathy | 34 | 183 | 1442959315024
|
||||
Jordan | West | 26 | 173 | 1442959315019
|
||||
Johnny | Zhang | 32 | 175 | 1442959315022
|
||||
|
||||
(7 rows)
|
||||
```
|
||||
|
||||
#### Equality & Prefix Queries
|
||||
|
||||
SASI supports all queries already supported by CQL, including LIKE statement
|
||||
for PREFIX, CONTAINS and SUFFIX searches.
|
||||
|
||||
```
|
||||
cqlsh:demo> SELECT first_name, last_name, age, height, created_at FROM sasi
|
||||
... WHERE first_name = 'Pavel';
|
||||
|
||||
first_name | last_name | age | height | created_at
|
||||
-------------+-----------+-----+--------+---------------
|
||||
Pavel | Yaskevich | 27 | 181 | 1442959315018
|
||||
|
||||
(1 rows)
|
||||
```
|
||||
|
||||
```
|
||||
cqlsh:demo> SELECT first_name, last_name, age, height, created_at FROM sasi
|
||||
... WHERE first_name = 'pavel';
|
||||
|
||||
first_name | last_name | age | height | created_at
|
||||
-------------+-----------+-----+--------+---------------
|
||||
Pavel | Yaskevich | 27 | 181 | 1442959315018
|
||||
|
||||
(1 rows)
|
||||
```
|
||||
|
||||
```
|
||||
cqlsh:demo> SELECT first_name, last_name, age, height, created_at FROM sasi
|
||||
... WHERE first_name LIKE 'M%';
|
||||
|
||||
first_name | last_name | age | height | created_at
|
||||
------------+-----------+-----+--------+---------------
|
||||
Michael | Kjellman | 26 | 180 | 1442959315021
|
||||
Mikhail | Stepura | 36 | 173 | 1442959315020
|
||||
|
||||
(2 rows)
|
||||
```
|
||||
|
||||
Of course, the case of the query does not matter for the `first_name`
|
||||
column because of the options provided at index creation time.
|
||||
|
||||
```
|
||||
cqlsh:demo> SELECT first_name, last_name, age, height, created_at FROM sasi
|
||||
... WHERE first_name LIKE 'm%';
|
||||
|
||||
first_name | last_name | age | height | created_at
|
||||
------------+-----------+-----+--------+---------------
|
||||
Michael | Kjellman | 26 | 180 | 1442959315021
|
||||
Mikhail | Stepura | 36 | 173 | 1442959315020
|
||||
|
||||
(2 rows)
|
||||
```
|
||||
|
||||
#### Compound Queries
|
||||
|
||||
SASI supports queries with multiple predicates, however, due to the
|
||||
nature of the default indexing implementation, CQL requires the user
|
||||
to specify `ALLOW FILTERING` to opt-in to the potential performance
|
||||
pitfalls of such a query. With SASI, while the requirement to include
|
||||
`ALLOW FILTERING` remains, to reduce modifications to the grammar, the
|
||||
performance pitfalls do not exist because filtering is not
|
||||
performed. Details on how SASI joins data from multiple predicates is
|
||||
available below in the
|
||||
[Implementation Details](#implementation-details)
|
||||
section.
|
||||
|
||||
```
|
||||
cqlsh:demo> SELECT first_name, last_name, age, height, created_at FROM sasi
|
||||
... WHERE first_name LIKE 'M%' and age < 30 ALLOW FILTERING;
|
||||
|
||||
first_name | last_name | age | height | created_at
|
||||
------------+-----------+-----+--------+---------------
|
||||
Michael | Kjellman | 26 | 180 | 1442959315021
|
||||
|
||||
(1 rows)
|
||||
```
|
||||
|
||||
#### Suffix Queries
|
||||
|
||||
The next example demonstrates `CONTAINS` mode on the `last_name`
|
||||
column. By using this mode predicates can search for any strings
|
||||
containing the search string as a sub-string. In this case the strings
|
||||
containing "a" or "an".
|
||||
|
||||
```
|
||||
cqlsh:demo> SELECT * FROM sasi WHERE last_name LIKE '%a%';
|
||||
|
||||
id | age | created_at | first_name | height | last_name
|
||||
--------------------------------------+-----+---------------+------------+--------+---------------
|
||||
f5dfcabe-de96-4148-9b80-a1c41ed276b4 | 26 | 1442959315021 | Michael | 180 | Kjellman
|
||||
96053844-45c3-4f15-b1b7-b02c441d3ee1 | 36 | 1442959315020 | Mikhail | 173 | Stepura
|
||||
556ebd54-cbe5-4b75-9aae-bf2a31a24500 | 27 | 1442959315018 | Pavel | 181 | Yaskevich
|
||||
8f909e8a-008e-49dd-8d43-1b0df348ed44 | 34 | 1442959315024 | Vijay | 183 | Parthasarathy
|
||||
2970da43-e070-41a8-8bcb-35df7a0e608a | 32 | 1442959315022 | Johnny | 175 | Zhang
|
||||
|
||||
(5 rows)
|
||||
|
||||
cqlsh:demo> SELECT * FROM sasi WHERE last_name LIKE '%an%';
|
||||
|
||||
id | age | created_at | first_name | height | last_name
|
||||
--------------------------------------+-----+---------------+------------+--------+-----------
|
||||
f5dfcabe-de96-4148-9b80-a1c41ed276b4 | 26 | 1442959315021 | Michael | 180 | Kjellman
|
||||
2970da43-e070-41a8-8bcb-35df7a0e608a | 32 | 1442959315022 | Johnny | 175 | Zhang
|
||||
|
||||
(2 rows)
|
||||
```
|
||||
|
||||
#### Expressions on Non-Indexed Columns
|
||||
|
||||
SASI also supports filtering on non-indexed columns like `height`. The
|
||||
expression can only narrow down an existing query using `AND`.
|
||||
|
||||
```
|
||||
cqlsh:demo> SELECT * FROM sasi WHERE last_name LIKE '%a%' AND height >= 175 ALLOW FILTERING;
|
||||
|
||||
id | age | created_at | first_name | height | last_name
|
||||
--------------------------------------+-----+---------------+------------+--------+---------------
|
||||
f5dfcabe-de96-4148-9b80-a1c41ed276b4 | 26 | 1442959315021 | Michael | 180 | Kjellman
|
||||
556ebd54-cbe5-4b75-9aae-bf2a31a24500 | 27 | 1442959315018 | Pavel | 181 | Yaskevich
|
||||
8f909e8a-008e-49dd-8d43-1b0df348ed44 | 34 | 1442959315024 | Vijay | 183 | Parthasarathy
|
||||
2970da43-e070-41a8-8bcb-35df7a0e608a | 32 | 1442959315022 | Johnny | 175 | Zhang
|
||||
|
||||
(4 rows)
|
||||
```
|
||||
|
||||
#### Text Analysis (Tokenization and Stemming)
|
||||
|
||||
Lastly, to demonstrate text analysis an additional column is needed on
|
||||
the table. Its definition, index, and statements to update rows are shown below.
|
||||
|
||||
```
|
||||
cqlsh:demo> ALTER TABLE sasi ADD bio text;
|
||||
cqlsh:demo> CREATE CUSTOM INDEX ON sasi (bio) USING 'org.apache.cassandra.index.sasi.SASIIndex'
|
||||
... WITH OPTIONS = {
|
||||
... 'analyzer_class': 'org.apache.cassandra.index.sasi.analyzer.StandardAnalyzer',
|
||||
... 'tokenization_enable_stemming': 'true',
|
||||
... 'analyzed': 'true',
|
||||
... 'tokenization_normalize_lowercase': 'true',
|
||||
... 'tokenization_locale': 'en'
|
||||
... };
|
||||
cqlsh:demo> UPDATE sasi SET bio = 'Software Engineer, who likes distributed systems, doesnt like to argue.' WHERE id = 5770382a-c56f-4f3f-b755-450e24d55217;
|
||||
cqlsh:demo> UPDATE sasi SET bio = 'Software Engineer, works on the freight distribution at nights and likes arguing' WHERE id = 556ebd54-cbe5-4b75-9aae-bf2a31a24500;
|
||||
cqlsh:demo> SELECT * FROM sasi;
|
||||
|
||||
id | age | bio | created_at | first_name | height | last_name
|
||||
--------------------------------------+-----+----------------------------------------------------------------------------------+---------------+------------+--------+---------------
|
||||
f5dfcabe-de96-4148-9b80-a1c41ed276b4 | 26 | null | 1442959315021 | Michael | 180 | Kjellman
|
||||
96053844-45c3-4f15-b1b7-b02c441d3ee1 | 36 | null | 1442959315020 | Mikhail | 173 | Stepura
|
||||
6b757016-631d-4fdb-ac62-40b127ccfbc7 | 40 | null | 1442959315023 | Jason | 182 | Brown
|
||||
556ebd54-cbe5-4b75-9aae-bf2a31a24500 | 27 | Software Engineer, works on the freight distribution at nights and likes arguing | 1442959315018 | Pavel | 181 | Yaskevich
|
||||
8f909e8a-008e-49dd-8d43-1b0df348ed44 | 34 | null | 1442959315024 | Vijay | 183 | Parthasarathy
|
||||
5770382a-c56f-4f3f-b755-450e24d55217 | 26 | Software Engineer, who likes distributed systems, doesnt like to argue. | 1442959315019 | Jordan | 173 | West
|
||||
2970da43-e070-41a8-8bcb-35df7a0e608a | 32 | null | 1442959315022 | Johnny | 175 | Zhang
|
||||
|
||||
(7 rows)
|
||||
```
|
||||
|
||||
Index terms and query search strings are stemmed for the `bio` column
|
||||
because it was configured to use the
|
||||
[`StandardAnalyzer`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/analyzer/StandardAnalyzer.java)
|
||||
and `analyzed` is set to `true`. The
|
||||
`tokenization_normalize_lowercase` is similar to the `case_sensitive`
|
||||
property but for the
|
||||
[`StandardAnalyzer`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/analyzer/StandardAnalyzer.java). These
|
||||
query demonstrates the stemming applied by [`StandardAnalyzer`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/analyzer/StandardAnalyzer.java).
|
||||
|
||||
```
|
||||
cqlsh:demo> SELECT * FROM sasi WHERE bio LIKE 'distributing';
|
||||
|
||||
id | age | bio | created_at | first_name | height | last_name
|
||||
--------------------------------------+-----+----------------------------------------------------------------------------------+---------------+------------+--------+-----------
|
||||
556ebd54-cbe5-4b75-9aae-bf2a31a24500 | 27 | Software Engineer, works on the freight distribution at nights and likes arguing | 1442959315018 | Pavel | 181 | Yaskevich
|
||||
5770382a-c56f-4f3f-b755-450e24d55217 | 26 | Software Engineer, who likes distributed systems, doesnt like to argue. | 1442959315019 | Jordan | 173 | West
|
||||
|
||||
(2 rows)
|
||||
|
||||
cqlsh:demo> SELECT * FROM sasi WHERE bio LIKE 'they argued';
|
||||
|
||||
id | age | bio | created_at | first_name | height | last_name
|
||||
--------------------------------------+-----+----------------------------------------------------------------------------------+---------------+------------+--------+-----------
|
||||
556ebd54-cbe5-4b75-9aae-bf2a31a24500 | 27 | Software Engineer, works on the freight distribution at nights and likes arguing | 1442959315018 | Pavel | 181 | Yaskevich
|
||||
5770382a-c56f-4f3f-b755-450e24d55217 | 26 | Software Engineer, who likes distributed systems, doesnt like to argue. | 1442959315019 | Jordan | 173 | West
|
||||
|
||||
(2 rows)
|
||||
|
||||
cqlsh:demo> SELECT * FROM sasi WHERE bio LIKE 'working at the company';
|
||||
|
||||
id | age | bio | created_at | first_name | height | last_name
|
||||
--------------------------------------+-----+----------------------------------------------------------------------------------+---------------+------------+--------+-----------
|
||||
556ebd54-cbe5-4b75-9aae-bf2a31a24500 | 27 | Software Engineer, works on the freight distribution at nights and likes arguing | 1442959315018 | Pavel | 181 | Yaskevich
|
||||
|
||||
(1 rows)
|
||||
|
||||
cqlsh:demo> SELECT * FROM sasi WHERE bio LIKE 'soft eng';
|
||||
|
||||
id | age | bio | created_at | first_name | height | last_name
|
||||
--------------------------------------+-----+----------------------------------------------------------------------------------+---------------+------------+--------+-----------
|
||||
556ebd54-cbe5-4b75-9aae-bf2a31a24500 | 27 | Software Engineer, works on the freight distribution at nights and likes arguing | 1442959315018 | Pavel | 181 | Yaskevich
|
||||
5770382a-c56f-4f3f-b755-450e24d55217 | 26 | Software Engineer, who likes distributed systems, doesnt like to argue. | 1442959315019 | Jordan | 173 | West
|
||||
|
||||
(2 rows)
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
While SASI, at the surface, is simply an implementation of the
|
||||
`Index` interface, at its core there are several data
|
||||
structures and algorithms used to satisfy it. These are described
|
||||
here. Additionally, the changes internal to Cassandra to support SASIs
|
||||
integration are described.
|
||||
|
||||
The `Index` interface divides responsibility of the
|
||||
implementer into two parts: Indexing and Querying. Further, Cassandra
|
||||
makes it possible to divide those responsibilities into the memory and
|
||||
disk components. SASI takes advantage of Cassandra's write-once,
|
||||
immutable, ordered data model to build indexes along with the flushing
|
||||
of the memtable to disk -- this is the origin of the name "SSTable
|
||||
Attached Secondary Index".
|
||||
|
||||
The SASI index data structures are built in memory as the SSTable is
|
||||
being written and they are flushed to disk before the writing of the
|
||||
SSTable completes. The writing of each index file only requires
|
||||
sequential writes to disk. In some cases, partial flushes are
|
||||
performed, and later stitched back together, to reduce memory
|
||||
usage. These data structures are optimized for this use case.
|
||||
|
||||
Taking advantage of Cassandra's ordered data model, at query time,
|
||||
candidate indexes are narrowed down for searching minimize the amount
|
||||
of work done. Searching is then performed using an efficient method
|
||||
that streams data off disk as needed.
|
||||
|
||||
### Indexing
|
||||
|
||||
Per SSTable, SASI writes an index file for each indexed column. The
|
||||
data for these files is built in memory using the
|
||||
[`OnDiskIndexBuilder`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/OnDiskIndexBuilder.java). Once
|
||||
flushed to disk, the data is read using the
|
||||
[`OnDiskIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/OnDiskIndex.java)
|
||||
class. These are composed of bytes representing indexed terms,
|
||||
organized for efficient writing or searching respectively. The keys
|
||||
and values they hold represent tokens and positions in an SSTable and
|
||||
these are stored per-indexed term in
|
||||
[`TokenTreeBuilder`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/TokenTreeBuilder.java)s
|
||||
for writing, and
|
||||
[`TokenTree`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/TokenTree.java)s
|
||||
for querying. These index files are memory mapped after being written
|
||||
to disk, for quicker access. For indexing data in the memtable SASI
|
||||
uses its
|
||||
[`IndexMemtable`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/IndexMemtable.java)
|
||||
class.
|
||||
|
||||
#### OnDiskIndex(Builder)
|
||||
|
||||
Each
|
||||
[`OnDiskIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/OnDiskIndex.java)
|
||||
is an instance of a modified
|
||||
[Suffix Array](https://en.wikipedia.org/wiki/Suffix_array) data
|
||||
structure. The
|
||||
[`OnDiskIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/OnDiskIndex.java)
|
||||
is comprised of page-size blocks of sorted terms and pointers to the
|
||||
terms' associated data, as well as the data itself, stored also in one
|
||||
or more page-sized blocks. The
|
||||
[`OnDiskIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/OnDiskIndex.java)
|
||||
is structured as a tree of arrays, where each level describes the
|
||||
terms in the level below, the final level being the terms
|
||||
themselves. The `PointerLevel`s and their `PointerBlock`s contain
|
||||
terms and pointers to other blocks that *end* with those terms. The
|
||||
`DataLevel`, the final level, and its `DataBlock`s contain terms and
|
||||
point to the data itself, contained in [`TokenTree`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/TokenTree.java)s.
|
||||
|
||||
The terms written to the
|
||||
[`OnDiskIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/OnDiskIndex.java)
|
||||
vary depending on its "mode": either `PREFIX`, `CONTAINS`, or
|
||||
`SPARSE`. In the `PREFIX` and `SPARSE` cases terms exact values are
|
||||
written exactly once per `OnDiskIndex`. For example, a `PREFIX` index
|
||||
with terms `Jason`, `Jordan`, `Pavel`, all three will be included in
|
||||
the index. A `CONTAINS` index writes additional terms for each suffix of
|
||||
each term recursively. Continuing with the example, a `CONTAINS` index
|
||||
storing the previous terms would also store `ason`, `ordan`, `avel`,
|
||||
`son`, `rdan`, `vel`, etc. This allows for queries on the suffix of
|
||||
strings. The `SPARSE` mode differs from `PREFIX` in that for every 64
|
||||
blocks of terms a
|
||||
[`TokenTree`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/TokenTree.java)
|
||||
is built merging all the
|
||||
[`TokenTree`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/TokenTree.java)s
|
||||
for each term into a single one. This copy of the data is used for
|
||||
efficient iteration of large ranges of e.g. timestamps. The index
|
||||
"mode" is configurable per column at index creation time.
|
||||
|
||||
#### TokenTree(Builder)
|
||||
|
||||
The
|
||||
[`TokenTree`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/TokenTree.java)
|
||||
is an implementation of the well-known
|
||||
[B+-tree](https://en.wikipedia.org/wiki/B%2B_tree) that has been
|
||||
modified to optimize for its use-case. In particular, it has been
|
||||
optimized to associate tokens, longs, with a set of positions in an
|
||||
SSTable, also longs. Allowing the set of long values accommodates
|
||||
the possibility of a hash collision in the token, but the data
|
||||
structure is optimized for the unlikely possibility of such a
|
||||
collision.
|
||||
|
||||
To optimize for its write-once environment the
|
||||
[`TokenTreeBuilder`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/TokenTreeBuilder.java)
|
||||
completely loads its interior nodes as the tree is built and it uses
|
||||
the well-known algorithm optimized for bulk-loading the data
|
||||
structure.
|
||||
|
||||
[`TokenTree`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/TokenTree.java)s provide the means to iterate a tokens, and file
|
||||
positions, that match a given term, and to skip forward in that
|
||||
iteration, an operation used heavily at query time.
|
||||
|
||||
#### IndexMemtable
|
||||
|
||||
The
|
||||
[`IndexMemtable`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/IndexMemtable.java)
|
||||
handles indexing the in-memory data held in the memtable. The
|
||||
[`IndexMemtable`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/IndexMemtable.java)
|
||||
in turn manages either a
|
||||
[`TrieMemIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/TrieMemIndex.java)
|
||||
or a
|
||||
[`SkipListMemIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/SkipListMemIndex.java)
|
||||
per-column. The choice of which index type is used is data
|
||||
dependent. The
|
||||
[`TrieMemIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/TrieMemIndex.java)
|
||||
is used for literal types. `AsciiType` and `UTF8Type` are literal
|
||||
types by defualt but any column can be configured as a literal type
|
||||
using the `is_literal` option at index creation time. For non-literal
|
||||
types the
|
||||
[`SkipListMemIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/SkipListMemIndex.java)
|
||||
is used. The
|
||||
[`TrieMemIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/TrieMemIndex.java)
|
||||
is an implementation that can efficiently support prefix queries on
|
||||
character-like data. The
|
||||
[`SkipListMemIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/SkipListMemIndex.java),
|
||||
conversely, is better suited for Cassandra other data types like
|
||||
numbers.
|
||||
|
||||
The
|
||||
[`TrieMemIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/TrieMemIndex.java)
|
||||
is built using either the `ConcurrentRadixTree` or
|
||||
`ConcurrentSuffixTree` from the `com.goooglecode.concurrenttrees`
|
||||
package. The choice between the two is made based on the indexing
|
||||
mode, `PREFIX` or other modes, and `CONTAINS` mode, respectively.
|
||||
|
||||
The
|
||||
[`SkipListMemIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/memory/SkipListMemIndex.java)
|
||||
is built on top of `java.util.concurrent.ConcurrentSkipListSet`.
|
||||
|
||||
### Querying
|
||||
|
||||
Responsible for converting the internal `IndexExpression`
|
||||
representation into SASI's
|
||||
[`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java)
|
||||
and
|
||||
[`Expression`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Expression.java)
|
||||
tree, optimizing the tree to reduce the amount of work done, and
|
||||
driving the query itself the
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java)
|
||||
is the work horse of SASI's querying implementation. To efficiently
|
||||
perform union and intersection operations SASI provides several
|
||||
iterators similar to Cassandra's `MergeIterator` but tailored
|
||||
specifically for SASIs use, and with more features. The
|
||||
[`RangeUnionIterator`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/utils/RangeUnionIterator.java),
|
||||
like its name suggests, performs set union over sets of tokens/keys
|
||||
matching the query, only reading as much data as it needs from each
|
||||
set to satisfy the query. The
|
||||
[`RangeIntersectionIterator`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/utils/RangeIntersectionIterator.java),
|
||||
similar to its counterpart, performs set intersection over its data.
|
||||
|
||||
#### QueryPlan
|
||||
|
||||
The
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java)
|
||||
instantiated per search query is at the core of SASIs querying
|
||||
implementation. Its work can be divided in two stages: analysis and
|
||||
execution.
|
||||
|
||||
During the analysis phase,
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java)
|
||||
converts from Cassandra's internal representation of
|
||||
`IndexExpression`s, which has also been modified to support encoding
|
||||
queries that contain ORs and groupings of expressions using
|
||||
parentheses (see the
|
||||
[Cassandra Internal Changes](#cassandra-internal-changes)
|
||||
section below for more details). This process produces a tree of
|
||||
[`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java)s, which in turn may contain [`Expression`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Expression.java)s, all of which
|
||||
provide an alternative, more efficient, representation of the query.
|
||||
|
||||
During execution the
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java)
|
||||
uses the `DecoratedKey`-generating iterator created from the
|
||||
[`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java) tree. These keys are read from disk and a final check to
|
||||
ensure they satisfy the query is made, once again using the
|
||||
[`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java) tree. At the point the desired amount of matching data has
|
||||
been found, or there is no more matching data, the result set is
|
||||
returned to the coordinator through the existing internal components.
|
||||
|
||||
The number of queries (total/failed/timed-out), and their latencies,
|
||||
are maintined per-table/column family.
|
||||
|
||||
SASI also supports concurrently iterating terms for the same index
|
||||
accross SSTables. The concurrency factor is controlled by the
|
||||
`cassandra.search_concurrency_factor` system property. The default is
|
||||
`1`.
|
||||
|
||||
##### QueryController
|
||||
|
||||
Each
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java)
|
||||
references a
|
||||
[`QueryController`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryController.java)
|
||||
used throughout the execution phase. The
|
||||
[`QueryController`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryController.java)
|
||||
has two responsibilities: to manage and ensure the proper cleanup of
|
||||
resources (indexes), and to strictly enforce the time bound for query,
|
||||
specified by the user via the range slice timeout. All indexes are
|
||||
accessed via the
|
||||
[`QueryController`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryController.java)
|
||||
so that they can be safely released by it later. The
|
||||
[`QueryController`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryController.java)'s
|
||||
`checkpoint` function is called in specific places in the execution
|
||||
path to ensure the time-bound is enforced.
|
||||
|
||||
##### QueryPlan Optimizations
|
||||
|
||||
While in the analysis phase, the
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java)
|
||||
performs several potential optimizations to the query. The goal of
|
||||
these optimizations is to reduce the amount of work performed during
|
||||
the execution phase.
|
||||
|
||||
The simplest optimization performed is compacting multiple expressions
|
||||
joined by logical intersection (`AND`) into a single [`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java) with
|
||||
three or more [`Expression`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Expression.java)s. For example, the query `WHERE age < 100 AND
|
||||
fname = 'p*' AND first_name != 'pa*' AND age > 21` would,
|
||||
without modification, have the following tree:
|
||||
|
||||
┌───────┐
|
||||
┌────────│ AND │──────┐
|
||||
│ └───────┘ │
|
||||
▼ ▼
|
||||
┌───────┐ ┌──────────┐
|
||||
┌─────│ AND │─────┐ │age < 100 │
|
||||
│ └───────┘ │ └──────────┘
|
||||
▼ ▼
|
||||
┌──────────┐ ┌───────┐
|
||||
│ fname=p* │ ┌─│ AND │───┐
|
||||
└──────────┘ │ └───────┘ │
|
||||
▼ ▼
|
||||
┌──────────┐ ┌──────────┐
|
||||
│fname!=pa*│ │ age > 21 │
|
||||
└──────────┘ └──────────┘
|
||||
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java)
|
||||
will remove the redundant right branch whose root is the final `AND`
|
||||
and has leaves `fname != pa*` and `age > 21`. These [`Expression`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Expression.java)s will
|
||||
be compacted into the parent `AND`, a safe operation due to `AND`
|
||||
being associative and commutative. The resulting tree looks like the
|
||||
following:
|
||||
|
||||
┌───────┐
|
||||
┌────────│ AND │──────┐
|
||||
│ └───────┘ │
|
||||
▼ ▼
|
||||
┌───────┐ ┌──────────┐
|
||||
┌───────────│ AND │────────┐ │age < 100 │
|
||||
│ └───────┘ │ └──────────┘
|
||||
▼ │ ▼
|
||||
┌──────────┐ │ ┌──────────┐
|
||||
│ fname=p* │ ▼ │ age > 21 │
|
||||
└──────────┘ ┌──────────┐ └──────────┘
|
||||
│fname!=pa*│
|
||||
└──────────┘
|
||||
|
||||
When excluding results from the result set, using `!=`, the
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java)
|
||||
determines the best method for handling it. For range queries, for
|
||||
example, it may be optimal to divide the range into multiple parts
|
||||
with a hole for the exclusion. For string queries, such as this one,
|
||||
it is more optimal, however, to simply note which data to skip, or
|
||||
exclude, while scanning the index. Following this optimization the
|
||||
tree looks like this:
|
||||
|
||||
┌───────┐
|
||||
┌────────│ AND │──────┐
|
||||
│ └───────┘ │
|
||||
▼ ▼
|
||||
┌───────┐ ┌──────────┐
|
||||
┌───────│ AND │────────┐ │age < 100 │
|
||||
│ └───────┘ │ └──────────┘
|
||||
▼ ▼
|
||||
┌──────────────────┐ ┌──────────┐
|
||||
│ fname=p* │ │ age > 21 │
|
||||
│ exclusions=[pa*] │ └──────────┘
|
||||
└──────────────────┘
|
||||
|
||||
The last type of optimization applied, for this query, is to merge
|
||||
range expressions across branches of the tree -- without modifying the
|
||||
meaning of the query, of course. In this case, because the query
|
||||
contains all `AND`s the `age` expressions can be collapsed. Along with
|
||||
this optimization, the initial collapsing of unneeded `AND`s can also
|
||||
be applied once more to result in this final tree using to execute the
|
||||
query:
|
||||
|
||||
┌───────┐
|
||||
┌──────│ AND │───────┐
|
||||
│ └───────┘ │
|
||||
▼ ▼
|
||||
┌──────────────────┐ ┌────────────────┐
|
||||
│ fname=p* │ │ 21 < age < 100 │
|
||||
│ exclusions=[pa*] │ └────────────────┘
|
||||
└──────────────────┘
|
||||
|
||||
#### Operations and Expressions
|
||||
|
||||
As discussed, the
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java)
|
||||
optimizes a tree represented by
|
||||
[`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java)s
|
||||
as interior nodes, and
|
||||
[`Expression`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Expression.java)s
|
||||
as leaves. The
|
||||
[`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java)
|
||||
class, more specifically, can have zero, one, or two
|
||||
[`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java)s
|
||||
as children and an unlimited number of expressions. The iterators used
|
||||
to perform the queries, discussed below in the
|
||||
"Range(Union|Intersection)Iterator" section, implement the necessary
|
||||
logic to merge results transparently regardless of the
|
||||
[`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java)s
|
||||
children.
|
||||
|
||||
Besides participating in the optimizations performed by the
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java),
|
||||
[`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java)
|
||||
is also responsible for taking a row that has been returned by the
|
||||
query and making a final validation that it in fact does match. This
|
||||
`satisfiesBy` operation is performed recursively from the root of the
|
||||
[`Operation`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java)
|
||||
tree for a given query. These checks are performed directly on the
|
||||
data in a given row. For more details on how `satisfiesBy` works see
|
||||
the documentation
|
||||
[in the code](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/Operation.java#L87-L123).
|
||||
|
||||
#### Range(Union|Intersection)Iterator
|
||||
|
||||
The abstract `RangeIterator` class provides a unified interface over
|
||||
the two main operations performed by SASI at various layers in the
|
||||
execution path: set intersection and union. These operations are
|
||||
performed in a iterated, or "streaming", fashion to prevent unneeded
|
||||
reads of elements from either set. In both the intersection and union
|
||||
cases the algorithms take advantage of the data being pre-sorted using
|
||||
the same sort order, e.g. term or token order.
|
||||
|
||||
The
|
||||
[`RangeUnionIterator`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/utils/RangeUnionIterator.java)
|
||||
performs the "Merge-Join" portion of the
|
||||
[Sort-Merge-Join](https://en.wikipedia.org/wiki/Sort-merge_join)
|
||||
algorithm, with the properties of an outer-join, or union. It is
|
||||
implemented with several optimizations to improve its performance over
|
||||
a large number of iterators -- sets to union. Specifically, the
|
||||
iterator exploits the likely case of the data having many sub-groups
|
||||
of overlapping ranges and the unlikely case that all ranges will
|
||||
overlap each other. For more details see the
|
||||
[javadoc](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/utils/RangeUnionIterator.java#L9-L21).
|
||||
|
||||
The
|
||||
[`RangeIntersectionIterator`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/utils/RangeIntersectionIterator.java)
|
||||
itself is not a subclass of `RangeIterator`. It is a container for
|
||||
several classes, one of which, `AbstractIntersectionIterator`,
|
||||
sub-classes `RangeIterator`. SASI supports two methods of performing
|
||||
the intersection operation, and the ability to be adaptive in choosing
|
||||
between them based on some properties of the data.
|
||||
|
||||
`BounceIntersectionIterator`, and the `BOUNCE` strategy, works like
|
||||
the
|
||||
[`RangeUnionIterator`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/utils/RangeUnionIterator.java)
|
||||
in that it performs a "Merge-Join", however, its nature is similar to
|
||||
a inner-join, where like values are merged by a data-specific merge
|
||||
function (e.g. merging two tokens in a list to lookup in a SSTable
|
||||
later). See the
|
||||
[javadoc](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/utils/RangeIntersectionIterator.java#L88-L101)
|
||||
for more details on its implementation.
|
||||
|
||||
`LookupIntersectionIterator`, and the `LOOKUP` strategy, performs a
|
||||
different operation, more similar to a lookup in an associative data
|
||||
structure, or "hash lookup" in database terminology. Once again,
|
||||
details on the implementation can be found in the
|
||||
[javadoc](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/utils/RangeIntersectionIterator.java#L199-L208).
|
||||
|
||||
The choice between the two iterators, or the `ADAPTIVE` strategy, is
|
||||
based upon the ratio of data set sizes of the minimum and maximum
|
||||
range of the sets being intersected. If the number of the elements in
|
||||
minimum range divided by the number of elements is the maximum range
|
||||
is less than or equal to `0.01`, then the `ADAPTIVE` strategy chooses
|
||||
the `LookupIntersectionIterator`, otherwise the
|
||||
`BounceIntersectionIterator` is chosen.
|
||||
|
||||
### The SASIIndex Class
|
||||
|
||||
The above components are glued together by the
|
||||
[`SASIIndex`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/SASIIndex.java)
|
||||
class which implements `Index`, and is instantiated
|
||||
per-table containing SASI indexes. It manages all indexes for a table
|
||||
via the
|
||||
[`sasi.conf.DataTracker`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/conf/DataTracker.java)
|
||||
and
|
||||
[`sasi.conf.view.View`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/conf/view/View.java)
|
||||
components, controls writing of all indexes for an SSTable via its
|
||||
[`PerSSTableIndexWriter`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/disk/PerSSTableIndexWriter.java), and initiates searches with
|
||||
`Searcher`. These classes glue the previously
|
||||
mentioned indexing components together with Cassandra's SSTable
|
||||
life-cycle ensuring indexes are not only written when Memtable's flush
|
||||
but also as SSTable's are compacted. For querying, the
|
||||
`Searcher` does little but defer to
|
||||
[`QueryPlan`](https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java)
|
||||
and update e.g. latency metrics exposed by SASI.
|
||||
|
||||
### Cassandra Internal Changes
|
||||
|
||||
To support the above changes and integrate them into Cassandra a few
|
||||
minor internal changes were made to Cassandra itself. These are
|
||||
described here.
|
||||
|
||||
#### SSTable Write Life-cycle Notifications
|
||||
|
||||
The `SSTableFlushObserver` is an observer pattern-like interface,
|
||||
whose sub-classes can register to be notified about events in the
|
||||
life-cycle of writing out a SSTable. Sub-classes can be notified when a
|
||||
flush begins and ends, as well as when each next row is about to be
|
||||
written, and each next column. SASI's `PerSSTableIndexWriter`,
|
||||
discussed above, is the only current subclass.
|
||||
|
||||
### Limitations and Caveats
|
||||
|
||||
The following are items that can be addressed in future updates but are not
|
||||
available in this repository or are not currently implemented.
|
||||
|
||||
* The cluster must be configured to use a partitioner that produces
|
||||
`LongToken`s, e.g. `Murmur3Partitioner`. Other existing partitioners which
|
||||
don't produce LongToken e.g. `ByteOrderedPartitioner` and `RandomPartitioner`
|
||||
will not work with SASI.
|
||||
* Not Equals and OR support have been removed in this release while
|
||||
changes are made to Cassandra itself to support them.
|
||||
|
||||
### Contributors
|
||||
|
||||
* [Pavel Yaskevich](https://github.com/xedin)
|
||||
* [Jordan West](https://github.com/jrwest)
|
||||
* [Michael Kjellman](https://github.com/mkjellman)
|
||||
* [Jason Brown](https://github.com/jasobrown)
|
||||
* [Mikhail Stepura](https://github.com/mishail)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
name: Cassandra
|
||||
title: Cassandra
|
||||
version: '3.11'
|
||||
display_version: '3.11'
|
||||
asciidoc:
|
||||
attributes:
|
||||
sectanchors: ''
|
||||
sectlinks: ''
|
||||
cass_url: 'http://cassandra.apache.org/'
|
||||
cass-docker-tag-3x: latest
|
||||
cass-tag-3x: '3.11'
|
||||
311_version: '3.11.10'
|
||||
30_version: '3.0.24'
|
||||
22_version: '2.2.19'
|
||||
21_version: '2.1.22'
|
||||
nav:
|
||||
- modules/ROOT/nav.adoc
|
||||
- modules/cassandra/nav.adoc
|
||||
299
doc/make.bat
|
|
@ -1,299 +0,0 @@
|
|||
@ECHO OFF
|
||||
|
||||
REM
|
||||
REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
REM or more contributor license agreements. See the NOTICE file
|
||||
REM distributed with this work for additional information
|
||||
REM regarding copyright ownership. The ASF licenses this file
|
||||
REM to you under the Apache License, Version 2.0 (the
|
||||
REM "License"); you may not use this file except in compliance
|
||||
REM with the License. You may obtain a copy of the License at
|
||||
REM
|
||||
REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
REM
|
||||
REM Unless required by applicable law or agreed to in writing, software
|
||||
REM distributed under the License is distributed on an "AS IS" BASIS,
|
||||
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
REM See the License for the specific language governing permissions and
|
||||
REM limitations under the License.
|
||||
REM
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
||||
set I18NSPHINXOPTS=%SPHINXOPTS% .
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. epub3 to make an epub3
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. texinfo to make Texinfo files
|
||||
echo. gettext to make PO message catalogs
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. xml to make Docutils-native XML files
|
||||
echo. pseudoxml to make pseudoxml-XML files for display purposes
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
echo. coverage to run coverage check of the documentation if enabled
|
||||
echo. dummy to check syntax errors of document sources
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
|
||||
REM Check if sphinx-build is available and fallback to Python version if any
|
||||
%SPHINXBUILD% 1>NUL 2>NUL
|
||||
if errorlevel 9009 goto sphinx_python
|
||||
goto sphinx_ok
|
||||
|
||||
:sphinx_python
|
||||
|
||||
set SPHINXBUILD=python -m sphinx.__init__
|
||||
%SPHINXBUILD% 2> nul
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:sphinx_ok
|
||||
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Foo.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Foo.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub3" (
|
||||
%SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub3 file is in %BUILDDIR%/epub3.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdf" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf
|
||||
cd %~dp0
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdfja" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf-ja
|
||||
cd %~dp0
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "texinfo" (
|
||||
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "gettext" (
|
||||
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "coverage" (
|
||||
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of coverage in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/coverage/python.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "xml" (
|
||||
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The XML files are in %BUILDDIR%/xml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pseudoxml" (
|
||||
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dummy" (
|
||||
%SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. Dummy builder generates no files.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
* xref:index.adoc[Main]
|
||||
** xref:master@_:ROOT:glossary.adoc[Glossary]
|
||||
** xref:master@_:ROOT:bugs.adoc[How to report bugs]
|
||||
** xref:master@_:ROOT:contactus.adoc[Contact us]
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
= Welcome to Apache Cassandra's documentation!
|
||||
|
||||
:description: Starting page for Apache Cassandra documentation.
|
||||
:keywords: Apache, Cassandra, NoSQL, database
|
||||
:cass-url: http://cassandra.apache.org
|
||||
:cass-contrib-url: https://wiki.apache.org/cassandra/HowToContribute
|
||||
|
||||
This is the official documentation for {cass-url}[Apache Cassandra].
|
||||
If you would like to contribute to this documentation, you are welcome
|
||||
to do so by submitting your contribution like any other patch following
|
||||
{cass-contrib-url}[these instructions].
|
||||
|
||||
== Main documentation
|
||||
|
||||
[cols="a,a"]
|
||||
|===
|
||||
|
||||
| xref:cassandra:getting_started/index.adoc[Getting started] | Newbie starting point
|
||||
|
||||
| xref:cassandra:architecture/index.adoc[Architecture] | Cassandra's big picture
|
||||
|
||||
| xref:cassandra:data_modeling/index.adoc[Data modeling] | Hint: it's not relational
|
||||
|
||||
| xref:cassandra:cql/index.adoc[Cassandra Query Language (CQL)] | CQL reference documentation
|
||||
|
||||
| xref:cassandra:configuration/index.adoc[Configuration] | Cassandra's handles and knobs
|
||||
|
||||
| xref:cassandra:operating/index.adoc[Operation] | The operator's corner
|
||||
|
||||
| xref:cassandra:tools/index.adoc[Tools] | cqlsh, nodetool, and others
|
||||
|
||||
| xref:cassandra:troubleshooting/index.adoc[Troubleshooting] | What to look for when you have a problem
|
||||
|
||||
| xref:cassandra:faq/index.adoc[FAQ] | Frequently asked questions
|
||||
|
||||
| xref:cassandra:plugins/index.adoc[Plug-ins] | Third-party plug-ins
|
||||
|
||||
| xref:master@_:ROOT:native_protocol.adoc[Native Protocols] | Native Cassandra protocol specifications
|
||||
|
||||
|===
|
||||
|
||||
== Meta information
|
||||
* xref:master@_:ROOT:bugs.adoc[Reporting bugs]
|
||||
* xref:master@_:ROOT:contactus.adoc[Contact us]
|
||||
* xref:master@_:ROOT:development/index.adoc[Contributing code]
|
||||
* xref:master@_:ROOT:docdev/index.adoc[Contributing to the docs]
|
||||
* xref:master@_:ROOT:community.adoc[Community]
|
||||
* xref:master@_:ROOT:download.adoc[Download]
|
||||
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 4.3 MiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 228 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 178 KiB |
|
After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 351 KiB |
|
|
@ -0,0 +1 @@
|
|||
$ curl https://www.apache.org/dist/cassandra/KEYS | sudo apt-key add -
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ sudo apt-get install cassandra
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ sudo apt-get update
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ cd ./cassandra/data/data/cqlkeyspace/t-d132e240c21711e9bbee19821dcea330/backups && ls -l
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ bin/cqlsh localhost
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ curl -OL http://apache.mirror.digitalpacific.com.au/cassandra/{cass-tag-3x}/apache-cassandra-{cass-tag-3x}-bin.tar.gz
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ curl -L https://downloads.apache.org/cassandra/{cass-tag-3x}/apache-cassandra-{cass-tag-3x}-bin.tar.gz.sha256
|
||||
|
|
@ -0,0 +1 @@
|
|||
docker exec -it cass_cluster cqlsh
|
||||
|
|
@ -0,0 +1 @@
|
|||
docker pull cassandra:{cass-docker-tag-3x}
|
||||
|
|
@ -0,0 +1 @@
|
|||
docker rm cassandra
|
||||
|
|
@ -0,0 +1 @@
|
|||
docker run --name cass_cluster cassandra:{cass-docker-tag-3x}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
docker run --rm -it -v /<currentdir>/scripts:/scripts \
|
||||
-v /<currentdir/cqlshrc:/.cassandra/cqlshrc \
|
||||
--env CQLSH_HOST=host.docker.internal --env CQLSH_PORT=9042 nuvo/docker-cqlsh
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ find -name backups
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ find -name snapshots
|
||||
|
|
@ -0,0 +1 @@
|
|||
find /var/lib/cassandra/data/ -type f | grep -v -- -ib- | grep -v "/snapshots"
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ cd ./cassandra/data/data/catalogkeyspace/journal-296a2d30c22a11e9b1350d927649052c/snapshots && ls -l
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
$ nodetool flush cqlkeyspace t
|
||||
$ cd ./cassandra/data/data/cqlkeyspace/t-d132e240c21711e9bbee19821dcea330/backups && ls -l
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
$ echo "deb http://www.apache.org/dist/cassandra/debian 311x main" | sudo tee -a /etc/apt/sources.list.d/cassandra.sources.list
|
||||
deb http://www.apache.org/dist/cassandra/debian 311x main
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ java -version
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool clearsnapshot -t magazine cqlkeyspace
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool clearsnapshot -all cqlkeyspace
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
$ nodetool flush cqlkeyspace t
|
||||
$ nodetool flush cqlkeyspace t2
|
||||
$ nodetool flush catalogkeyspace journal magazine
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool flush cqlkeyspace t
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool listsnapshots
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool help snapshot
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ bin/nodetool status
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool status
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ bin/cqlsh
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ cqlsh
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool snapshot --tag catalog-ks catalogkeyspace
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool snapshot --tag catalog-cql-ks catalogkeyspace, cqlkeyspace
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ cd catalog-ks && ls -l
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool snapshot --kt-list catalogkeyspace.journal,cqlkeyspace.t --tag multi-ks
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool snapshot --kt-list cqlkeyspace.t,cqlkeyspace.t2 --tag multi-table
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool snapshot --kt-list cqlkeyspace.t, cqlkeyspace.t2 --tag multi-table-2
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool snapshot --tag <tag> --table <table> --<keyspace>
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ nodetool snapshot --tag magazine --table magazine catalogkeyspace
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ cd apache-cassandra-{cass-tag-3x}/ && bin/cassandra
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ tail -f logs/system.log
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ tail -f /var/log/cassandra/system.log
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ tar xzvf apache-cassandra-{cass-tag-3x}-bin.tar.gz
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ gpg --print-md SHA256 apache-cassandra-{cass-tag-3x}-bin.tar.gz
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ sudo yum install cassandra
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ sudo service cassandra start
|
||||
|
|
@ -0,0 +1 @@
|
|||
$ sudo yum update
|
||||
|
|
@ -0,0 +1 @@
|
|||
aggregate_name::= [keyspace_name '.' ] name
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
alter_keyspace_statement::= ALTER KEYSPACE keyspace_name
|
||||
WITH options
|
||||
|
|
@ -0,0 +1 @@
|
|||
alter_materialized_view_statement::= ALTER MATERIALIZED VIEW view_name WITH table_options
|
||||
|
|
@ -0,0 +1 @@
|
|||
alter_role_statement ::= ALTER ROLE role_name WITH role_options
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
alter_table_statement::= ALTER TABLE table_name alter_table_instruction
|
||||
alter_table_instruction::= ADD column_name cql_type ( ',' column_name cql_type )*
|
||||
| DROP column_name ( column_name )*
|
||||
| WITH options
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
alter_type_statement::= ALTER TYPE udt_name alter_type_modification
|
||||
alter_type_modification::= ADD field_definition
|
||||
| RENAME identifier TO identifier( identifier TO identifier )*
|
||||
|
|
@ -0,0 +1 @@
|
|||
alter_user_statement ::= ALTER USER role_name [ WITH PASSWORD string] [ user_option]
|
||||